From patchwork Thu Jul 9 13:28:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8716 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id BA099BD792 for ; Thu, 9 Jul 2020 13:28:52 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8673661214; Thu, 9 Jul 2020 15:28:52 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oAq0Tb7c"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E576D61184 for ; Thu, 9 Jul 2020 15:28:50 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9CDA1525; Thu, 9 Jul 2020 15:28:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301330; bh=UOumBP0zUP+8kmbweOg3p6V9in0XH+WFBCG2X64UQUk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oAq0Tb7cYAWKEELeCjns3408RdrptWIrsDrqzm+J1YvRgElf1P2+4QIiYUgoN0JCW 9iiMY4W06IIln+TKcJjGayhhowMVghZMxAt60z+6UUGQCNWChdB7kofIpDJ1GF02Rh +I+73kMdWd0wVbgBy5hZOhK2xurSfZ5VA4sM12aw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:13 +0900 Message-Id: <20200709132835.112593-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 01/23] libcamera: formats: Add NV24 and NV42, and reorder NV formats 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add formats for NV24 and NV42. While at it, reorder the NV formats so that NV12 and NV21 come first, followed by NV16, NV61, NV24, and NV42. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- No change in v5 No change in v4 No change in v3 --- src/libcamera/formats.cpp | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index 436672e..d3b722c 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -256,6 +256,22 @@ const std::map pixelFormatInfo{ } }, /* YUV planar formats. */ + { formats::NV12, { + .name = "NV12", + .format = formats::NV12, + .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV12), + .bitsPerPixel = 12, + .colourEncoding = PixelFormatInfo::ColourEncodingYUV, + .packed = false, + } }, + { formats::NV21, { + .name = "NV21", + .format = formats::NV21, + .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV21), + .bitsPerPixel = 12, + .colourEncoding = PixelFormatInfo::ColourEncodingYUV, + .packed = false, + } }, { formats::NV16, { .name = "NV16", .format = formats::NV16, @@ -272,19 +288,19 @@ const std::map pixelFormatInfo{ .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, } }, - { formats::NV12, { - .name = "NV12", - .format = formats::NV12, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV12), - .bitsPerPixel = 12, + { formats::NV24, { + .name = "NV24", + .format = formats::NV24, + .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV24), + .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, } }, - { formats::NV21, { - .name = "NV21", - .format = formats::NV21, - .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV21), - .bitsPerPixel = 12, + { formats::NV42, { + .name = "NV42", + .format = formats::NV42, + .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV42), + .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, } }, From patchwork Thu Jul 9 13:28:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8717 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 15946BD792 for ; Thu, 9 Jul 2020 13:28:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D5FAE6121D; Thu, 9 Jul 2020 15:28:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="cOlW+dwt"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 011D161184 for ; Thu, 9 Jul 2020 15:28:54 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4A60C525; Thu, 9 Jul 2020 15:28:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301333; bh=2cbNYJyLfZmn/gHZyIqLeMm7sRXatlZLvw1LzCh2APk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cOlW+dwt0F6rJr6GC3yIxEf083k6EOpV/gTTVkRxynBvAxM4R77BreSpGE/7ZzbK7 RLLRZT3KKSls3SeDeVVnikJkivZPz0rfKNZTCWMZjg8iPuAnyAEwVXaAZcjumPplAM CbUB3iof0V9anb+IhSNoHo8ebGr1IaQMz80vaY4s= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:14 +0900 Message-Id: <20200709132835.112593-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 02/23] libcamera: formats: Add fields to info to ease calculating stride 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Packed formats make it difficult to calculate stride as well as frame size with the fields that PixelFormatInfo currently has. bitsPerPixel is defined as the average number of bits per pixel, and only counts effective bits, so it is not useful for calculating stride and frame size. To fix this, we introduce a concept of a "pixel group". The size of this group is defined as the minimum number of pixels (including padding) necessary in a row when the image has only one column of effective pixels. The pixel group has one more attribute, that is the "bytes per group". This determines how many bytes one pixel group consumes. These are the fields pixelsPerGroup and bytesPerGroup that are defined in this patch. Defining these two values makes it really simple to calculate bytes-per-line, as ceil(width / pixelsPerGroup) * bytesPerGroup, where width is measured in number of pixels. The ceiling accounts for padding. The pixel group has another contraint, which is that the pixel group (bytesPerGroup and pixelsPerGroup) is the smallest repeatable unit. What this means is that, for example, in the IPU3 formats, if there is only one column of effective pixels, it looks like it could be fit in 5 bytes with 3 padding pixels (for a total of 4 pixels over 5 bytes). However, this unit is not repeatable, as at the 7th group in the same row, the pattern is broken. Therefore, the pixel group for IPU3 formats must be 25 pixels over 32 bytes. Clearly, pixelsPerGroup must be constant for all planes in the format. The bytesPerGroup then, must be a per-plane attribute. There is one more field, verticalSubSampling, that is per-plane. This is simply a divider, to divide the number of rows of pixels by the sub-sampling value, to obtain the number of rows of pixels for the subsampled plane. For example, for something simple like BGR888, it is self-explanatory: the pixel group size is 1, and the bytes necessary is 3, and there is only one plane with no (= 1) vertical subsampling. For YUYV, the CbCr pair is shared between two pixels, so even if you have only one pixel, you would still need a padded second Y, therefore the pixel group size is 2, and bytes necessary is 4 (as opposed to 1 and 2). YUYV also has no vertical subsampling. NV12 has a pixel group size of 2 pixels, due to the CbCr plane. The bytes per group then, for both planes, is 2. The first plane has no vertical subsampling, but the second plane is subsampled by a factor of 2. The IPU3 formats are also self-explanatory, as they are single-planar, and have a pixel group size of 25, consuming 32 bytes. Although a comment in the driver suggests that it should be 50 and 64, respectively, this is an attribute of the driver, and not the format, so this shall be set by the ipu3 pipeline handler. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- Changes in v5: - add #include to fix cros compile error Changes in v4: - expanded documentation and definition of pixel group Changes in v3: - add planes - redefine the parameters for the formats - pixelsPerGroup is for whole format - add verticalSubSampling per plane Changes in v2: - add documentation for bytesPerGroup pixelsPerGroup - fix wording in commit message - bytes-per-line -> stride - buffer size -> frame size - changed MJPEG todo to allowing pipeline handlers to set parameters of format infos --- include/libcamera/internal/formats.h | 11 ++ src/libcamera/formats.cpp | 148 +++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index f59ac8f..4e90e5a 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -8,6 +8,7 @@ #ifndef __LIBCAMERA_INTERNAL_FORMATS_H__ #define __LIBCAMERA_INTERNAL_FORMATS_H__ +#include #include #include @@ -32,6 +33,12 @@ private: std::map> data_; }; +struct PixelFormatPlaneInfo +{ + unsigned int bytesPerGroup; + unsigned int verticalSubSampling; +}; + class PixelFormatInfo { public: @@ -52,6 +59,10 @@ public: unsigned int bitsPerPixel; enum ColourEncoding colourEncoding; bool packed; + + unsigned int pixelsPerGroup; + + std::array planes; }; } /* namespace libcamera */ diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index d3b722c..e6d3d3b 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -110,6 +110,22 @@ const std::map> &ImageFormats::data() const return data_; } +/** + * \class PixelFormatPlaneInfo + * \brief Information about a single plane of a pixel format + * + * \var PixelFormatPlaneInfo::bytesPerGroup + * \brief The number of bytes that a pixel group consumes + * + * \sa PixelFormatInfo::pixelsPerGroup + * + * \var PixelFormatPlaneInfo::verticalSubSampling + * \brief Vertical subsampling multiplier + * + * This value is the ratio between the number of rows of pixels in the frame + * to the number of rows of pixels in the plane. + */ + /** * \class PixelFormatInfo * \brief Information about pixel formats @@ -152,6 +168,49 @@ const std::map> &ImageFormats::data() const * bytes. For instance, 12-bit Bayer data with two pixels stored in three bytes * is packed, while the same data stored with 4 bits of padding in two bytes * per pixel is not packed. + * + * \var PixelFormatInfo::pixelsPerGroup + * \brief The number of pixels in a pixel group + * + * The minimum number of pixels (including padding) necessary in a row + * when the frame has only one column of effective pixels. + * + * A pixel group is defined as the minimum number of pixels (including padding) + * necessary in a row when the image has only one column of effective pixels. + * pixelsPerGroup refers to this value. PixelFormatPlaneInfo::bytesPerGroup, + * then, refers to the number of bytes that a pixel group consumes. This + * definition of a pixel group allows simple calculation of stride, as + * ceil(width / pixelsPerGroup) * bytesPerGroup. These values are determined + * only in terms of a row. The ceiling accounts for padding. + * + * A pixel group has a second constraint, such that the pixel group + * (bytesPerGroup and pixelsPerGroup) is the smallest repeatable unit. + * What this means is that, for example, in the IPU3 formats, if there is only + * one column of effective pixels, it looks like it could be fit in 5 bytes + * with 3 padding pixels (for a total of 4 pixels over 5 bytes). However, this + * unit is not repeatable, as at the 7th group in the same row, the pattern + * is broken. Therefore, the pixel group for IPU3 formats must be 25 pixels + * over 32 bytes. + * + * For example, for something simple like BGR888, it is self-explanatory: + * the pixel group size is 1, and the bytes necessary is 3, and there is + * only one plane with no (= 1) vertical subsampling. For YUYV, the + * CbCr pair is shared between two pixels, so even if you have only one + * pixel, you would still need a padded second Y sample, therefore the pixel + * group size is 2, and bytes necessary is 4. YUYV also has no vertical + * subsampling. NV12 has a pixel group size of 2 pixels, due to the CbCr plane. + * The bytes per group then, for both planes, is 2. The first plane has no + * vertical subsampling, but the second plane is subsampled by a factor of 2. + * The IPU3 formats are also self-explanatory, as they are single-planar, + * and have a pixel group size of 25, consuming 32 bytes. Although a + * comment in the driver suggests that it should be 50 and 64, + * respectively, this is an attribute of the driver, and not the format, so + * this shall be set by the ipu3 pipeline handler. + * + * \var PixelFormatInfo::planes + * \brief Information about pixels for each plane + * + * \sa PixelFormatPlaneInfo */ /** @@ -179,6 +238,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::RGB888, { .name = "RGB888", @@ -187,6 +248,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::ABGR8888, { .name = "ABGR8888", @@ -195,6 +258,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::ARGB8888, { .name = "ARGB8888", @@ -203,6 +268,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::BGRA8888, { .name = "BGRA8888", @@ -211,6 +278,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::RGBA8888, { .name = "RGBA8888", @@ -219,6 +288,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, /* YUV packed formats. */ @@ -229,6 +300,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::YVYU, { .name = "YVYU", @@ -237,6 +310,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::UYVY, { .name = "UYVY", @@ -245,6 +320,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::VYUY, { .name = "VYUY", @@ -253,6 +330,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, /* YUV planar formats. */ @@ -263,6 +342,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 2, 2 }, { 0, 0 } }}, } }, { formats::NV21, { .name = "NV21", @@ -271,6 +352,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 2, 2 }, { 0, 0 } }}, } }, { formats::NV16, { .name = "NV16", @@ -279,6 +362,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 2, 1 }, { 0, 0 } }}, } }, { formats::NV61, { .name = "NV61", @@ -287,6 +372,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 2, 1 }, { 0, 0 } }}, } }, { formats::NV24, { .name = "NV24", @@ -295,6 +382,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 1, 1 }, { 2, 1 }, { 0, 0 } }}, } }, { formats::NV42, { .name = "NV42", @@ -303,6 +392,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 1, 1 }, { 2, 1 }, { 0, 0 } }}, } }, { formats::YUV420, { .name = "YUV420", @@ -311,6 +402,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 1, 2 }, { 1, 2 } }}, } }, { formats::YUV422, { .name = "YUV422", @@ -319,6 +412,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 1, 1 }, { 1, 1 } }}, } }, /* Greyscale formats. */ @@ -329,6 +424,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 1, 1 }, { 0, 0 }, { 0, 0 } }}, } }, /* Bayer formats. */ @@ -339,6 +436,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGBRG8, { .name = "SGBRG8", @@ -347,6 +446,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGRBG8, { .name = "SGRBG8", @@ -355,6 +456,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SRGGB8, { .name = "SRGGB8", @@ -363,6 +466,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SBGGR10, { .name = "SBGGR10", @@ -371,6 +476,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGBRG10, { .name = "SGBRG10", @@ -379,6 +486,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGRBG10, { .name = "SGRBG10", @@ -387,6 +496,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SRGGB10, { .name = "SRGGB10", @@ -395,6 +506,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SBGGR10_CSI2P, { .name = "SBGGR10_CSI2P", @@ -403,6 +516,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 4, + .planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGBRG10_CSI2P, { .name = "SGBRG10_CSI2P", @@ -411,6 +526,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 4, + .planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGRBG10_CSI2P, { .name = "SGRBG10_CSI2P", @@ -419,6 +536,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 4, + .planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SRGGB10_CSI2P, { .name = "SRGGB10_CSI2P", @@ -427,6 +546,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 4, + .planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SBGGR12, { .name = "SBGGR12", @@ -435,6 +556,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGBRG12, { .name = "SGBRG12", @@ -443,6 +566,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGRBG12, { .name = "SGRBG12", @@ -451,6 +576,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SRGGB12, { .name = "SRGGB12", @@ -459,6 +586,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .pixelsPerGroup = 2, + .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SBGGR12_CSI2P, { .name = "SBGGR12_CSI2P", @@ -467,6 +596,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 2, + .planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGBRG12_CSI2P, { .name = "SGBRG12_CSI2P", @@ -475,6 +606,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 2, + .planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGRBG12_CSI2P, { .name = "SGRBG12_CSI2P", @@ -483,6 +616,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 2, + .planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SRGGB12_CSI2P, { .name = "SRGGB12_CSI2P", @@ -491,6 +626,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 2, + .planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SBGGR10_IPU3, { .name = "SBGGR10_IPU3", @@ -499,6 +636,9 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + /* \todo remember to double this in the ipu3 pipeline handler */ + .pixelsPerGroup = 25, + .planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGBRG10_IPU3, { .name = "SGBRG10_IPU3", @@ -507,6 +647,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 25, + .planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SGRBG10_IPU3, { .name = "SGRBG10_IPU3", @@ -515,6 +657,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 25, + .planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }}, } }, { formats::SRGGB10_IPU3, { .name = "SRGGB10_IPU3", @@ -523,6 +667,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .pixelsPerGroup = 25, + .planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }}, } }, /* Compressed formats. */ @@ -533,6 +679,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 0, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .pixelsPerGroup = 1, + .planes = {{ { 1, 1 }, { 0, 0 }, { 0, 0 } }}, } }, }; From patchwork Thu Jul 9 13:28:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8718 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8E015BD792 for ; Thu, 9 Jul 2020 13:28:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5BB7661224; Thu, 9 Jul 2020 15:28:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="EzCwjNQf"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 466DF6121E for ; Thu, 9 Jul 2020 15:28:56 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5A34E56E; Thu, 9 Jul 2020 15:28:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301335; bh=Sw0aLZ4tekKrRXFGfRP186lv/HOJyhfIHNHMLQbRQAE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EzCwjNQfTOz6qBYBZS6FQDhkXoPcoAIg502+aVL3OtSZggSR5sCM8Xv32QXqNATNr odtsToGuVqbJIT/e7K2B+Hm7Bhj5xWEGtKmpDOaI6p6jiPxK6c0DGAyMQwpPWW3LDP aG9W0V/AUf04jnIdvsuUwZLlDM5twSfuKrtSb8r0= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:15 +0900 Message-Id: <20200709132835.112593-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 03/23] libcamera: StreamConfiguration: Add frameSize field 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In addition to the stride field, we want the pipeline handler to be able to declare the frame size for the configuration. Add a frameSize field to StreamConfiguration for this purpose. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- No change in v5 No change in v4 New in v3 --- include/libcamera/stream.h | 1 + src/libcamera/stream.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index 1a68bd2..f502b35 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -43,6 +43,7 @@ struct StreamConfiguration { PixelFormat pixelFormat; Size size; unsigned int stride; + unsigned int frameSize; unsigned int bufferCount; diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index 6df5882..6d6e279 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -279,7 +279,8 @@ SizeRange StreamFormats::range(const PixelFormat &pixelformat) const * handlers provide StreamFormats. */ StreamConfiguration::StreamConfiguration() - : pixelFormat(0), stride(0), bufferCount(0), stream_(nullptr) + : pixelFormat(0), stride(0), frameSize(0), bufferCount(0), + stream_(nullptr) { } @@ -287,8 +288,8 @@ StreamConfiguration::StreamConfiguration() * \brief Construct a configuration with stream formats */ StreamConfiguration::StreamConfiguration(const StreamFormats &formats) - : pixelFormat(0), stride(0), bufferCount(0), stream_(nullptr), - formats_(formats) + : pixelFormat(0), stride(0), frameSize(0), bufferCount(0), + stream_(nullptr), formats_(formats) { } @@ -315,6 +316,16 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats) * the camera is configured. */ +/** + * \var StreamConfiguration::frameSize + * \brief Frame size for the stream, in bytes + * + * The frameSize value reports the number of bytes necessary to contain one + * frame of an image buffer for this stream. The value is valid after + * successfully validating the configuration with a call to + * CameraConfiguration::validate(). + */ + /** * \var StreamConfiguration::bufferCount * \brief Requested number of buffers to allocate for the stream From patchwork Thu Jul 9 13:28:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8719 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 029EDBD792 for ; Thu, 9 Jul 2020 13:29:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C500861218; Thu, 9 Jul 2020 15:29:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qvuyi2Le"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D0FD261184 for ; Thu, 9 Jul 2020 15:28:58 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9A163525; Thu, 9 Jul 2020 15:28:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301338; bh=PxDSet/16HucKK+x7HS6TY+XJlYm0Q10XoAIslw2Nlc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qvuyi2LeobF0VNAPgLMxW3T9cAYoC7bL32A7YEoSo2NLytMMlNgS7C159w5/5hlBE ip3ByCeW533tHKa0Pqj8Vl49r3fKGVjqQc1wenFog7XaMvdPGsdWzKdDNsVFWTkkho 1yDz9kgkLdS+Ys2Ep1GUu6oU1voNM9TKa/d/uwZg= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:16 +0900 Message-Id: <20200709132835.112593-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 04/23] libcamera: V4L2VideoDevice: Add tryFormat 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add tryFormat and its variations (meta, single-plane, multi-plane) to V4L2VideoDevice. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- Cosmetic change in v5 Changes in v4: - merge tryFormat{Meta,Multiplane,SinglePlane} into setFormat with a flag New in v3 --- include/libcamera/internal/v4l2_videodevice.h | 7 +-- src/libcamera/v4l2_videodevice.cpp | 50 ++++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h index 4d21f5a..fb4c0aa 100644 --- a/include/libcamera/internal/v4l2_videodevice.h +++ b/include/libcamera/internal/v4l2_videodevice.h @@ -186,6 +186,7 @@ public: const V4L2Capability &caps() const { return caps_; } int getFormat(V4L2DeviceFormat *format); + int tryFormat(V4L2DeviceFormat *format); int setFormat(V4L2DeviceFormat *format); std::map> formats(uint32_t code = 0); @@ -217,13 +218,13 @@ protected: private: int getFormatMeta(V4L2DeviceFormat *format); - int setFormatMeta(V4L2DeviceFormat *format); + int trySetFormatMeta(V4L2DeviceFormat *format, bool set); int getFormatMultiplane(V4L2DeviceFormat *format); - int setFormatMultiplane(V4L2DeviceFormat *format); + int trySetFormatMultiplane(V4L2DeviceFormat *format, bool set); int getFormatSingleplane(V4L2DeviceFormat *format); - int setFormatSingleplane(V4L2DeviceFormat *format); + int trySetFormatSingleplane(V4L2DeviceFormat *format, bool set); std::vector enumPixelformats(uint32_t code); std::vector enumSizes(V4L2PixelFormat pixelFormat); diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 3614b2e..e0d2201 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -723,6 +723,26 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format) return getFormatSingleplane(format); } +/** + * \brief Try an image format on the V4L2 video device + * \param[inout] format The image format to test applicability to the video device + * + * Try the supplied \a format on the video device without applying it, returning + * the format that would be applied. This is equivalent to setFormat(), except + * that the device configuration is not changed. + * + * \return 0 on success or a negative error code otherwise + */ +int V4L2VideoDevice::tryFormat(V4L2DeviceFormat *format) +{ + if (caps_.isMeta()) + return trySetFormatMeta(format, false); + else if (caps_.isMultiplanar()) + return trySetFormatMultiplane(format, false); + else + return trySetFormatSingleplane(format, false); +} + /** * \brief Configure an image format on the V4L2 video device * \param[inout] format The image format to apply to the video device @@ -735,11 +755,11 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format) int V4L2VideoDevice::setFormat(V4L2DeviceFormat *format) { if (caps_.isMeta()) - return setFormatMeta(format); + return trySetFormatMeta(format, true); else if (caps_.isMultiplanar()) - return setFormatMultiplane(format); + return trySetFormatMultiplane(format, true); else - return setFormatSingleplane(format); + return trySetFormatSingleplane(format, true); } int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format) @@ -765,7 +785,7 @@ int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format) return 0; } -int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format) +int V4L2VideoDevice::trySetFormatMeta(V4L2DeviceFormat *format, bool set) { struct v4l2_format v4l2Format = {}; struct v4l2_meta_format *pix = &v4l2Format.fmt.meta; @@ -774,9 +794,11 @@ int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format) v4l2Format.type = bufferType_; pix->dataformat = format->fourcc; pix->buffersize = format->planes[0].size; - ret = ioctl(VIDIOC_S_FMT, &v4l2Format); + ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format); if (ret) { - LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); + LOG(V4L2, Error) + << "Unable to " << (set ? "set" : "try") + << " format: " << strerror(-ret); return ret; } @@ -820,7 +842,7 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format) return 0; } -int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format) +int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set) { struct v4l2_format v4l2Format = {}; struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp; @@ -838,9 +860,11 @@ int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format) pix->plane_fmt[i].sizeimage = format->planes[i].size; } - ret = ioctl(VIDIOC_S_FMT, &v4l2Format); + ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format); if (ret) { - LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); + LOG(V4L2, Error) + << "Unable to " << (set ? "set" : "try") + << " format: " << strerror(-ret); return ret; } @@ -883,7 +907,7 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format) return 0; } -int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format) +int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set) { struct v4l2_format v4l2Format = {}; struct v4l2_pix_format *pix = &v4l2Format.fmt.pix; @@ -895,9 +919,11 @@ int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format) pix->pixelformat = format->fourcc; pix->bytesperline = format->planes[0].bpl; pix->field = V4L2_FIELD_NONE; - ret = ioctl(VIDIOC_S_FMT, &v4l2Format); + ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format); if (ret) { - LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret); + LOG(V4L2, Error) + << "Unable to " << (set ? "set" : "try") + << " format: " << strerror(-ret); return ret; } From patchwork Thu Jul 9 13:28:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8720 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 621A8BD792 for ; Thu, 9 Jul 2020 13:29:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2EDB761214; Thu, 9 Jul 2020 15:29:03 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="APnaTAPl"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 41F4A61184 for ; Thu, 9 Jul 2020 15:29:01 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 60637525; Thu, 9 Jul 2020 15:28:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301341; bh=yZ6rmuidz6coF/A8M2ObiHffxyzDcmI8NW9wNDESm8c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=APnaTAPlc/90oprJWt9y6PV7alz5+WJv/NfHDPOBIuEZJ0BrA4eSI/ceU9omn+lWU CijkuKr00ZHVU6Bcq1M28AdG0OgvNtpk7os0Y4nM/FaSj93G6AuEvJeyaYw3UngOMn cr1Gc+/RCGYnQA2jhJecwE4NUWli3HrCaGI5WtR4= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:17 +0900 Message-Id: <20200709132835.112593-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 05/23] libcamera: formats: PixelFormatInfo: Add v4l2 lookup function 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a lookup function for PixelFormatInfo that takes a V4L2PixelFormat. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v5 No change in v4 Changes in v3: - rename invalid PixelFormatInfo - make info const in PixelFormatInfo::info() Changes in v2: - move invalid PixelFormatInfo instance to anonymous namespace - add documentation --- include/libcamera/internal/formats.h | 1 + src/libcamera/formats.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index 4e90e5a..211da4a 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -51,6 +51,7 @@ public: bool isValid() const { return format.isValid(); } static const PixelFormatInfo &info(const PixelFormat &format); + static const PixelFormatInfo &info(const V4L2PixelFormat &format); /* \todo Add support for non-contiguous memory planes */ const char *name; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index e6d3d3b..6d96055 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -7,6 +7,7 @@ #include "libcamera/internal/formats.h" +#include #include #include @@ -229,6 +230,8 @@ const std::map> &ImageFormats::data() const namespace { +const PixelFormatInfo pixelFormatInfoInvalid{}; + const std::map pixelFormatInfo{ /* RGB formats. */ { formats::BGR888, { @@ -700,17 +703,33 @@ const std::map pixelFormatInfo{ */ const PixelFormatInfo &PixelFormatInfo::info(const PixelFormat &format) { - static const PixelFormatInfo invalid{}; - const auto iter = pixelFormatInfo.find(format); if (iter == pixelFormatInfo.end()) { LOG(Formats, Warning) << "Unsupported pixel format 0x" << utils::hex(format.fourcc()); - return invalid; + return pixelFormatInfoInvalid; } return iter->second; } +/** + * \brief Retrieve information about a pixel format + * \param[in] format The V4L2 pixel format + * \return The PixelFormatInfo describing the V4L2 \a format if known, or an + * invalid PixelFormatInfo otherwise + */ +const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format) +{ + const auto &info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), + [format](auto pair) { + return pair.second.v4l2Format == format; + }); + if (info == pixelFormatInfo.end()) + return pixelFormatInfoInvalid; + + return info->second; +} + } /* namespace libcamera */ From patchwork Thu Jul 9 13:28:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8721 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B2D3ABD792 for ; Thu, 9 Jul 2020 13:29:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8202F61218; Thu, 9 Jul 2020 15:29:05 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="urQQwHjS"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8C6EE61184 for ; Thu, 9 Jul 2020 15:29:04 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B6F24525; Thu, 9 Jul 2020 15:29:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301343; bh=Myx76QvUqwfMypzOWC1GMNsc6zeXn6XAate9783uJ2E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=urQQwHjSmGbCAXS6ux8D8Fw2Hun98M3eartk0sXS8PDJxsQO+Ru5mNS0FK806DqWW aSnLUZgORUiFRjDyirlShwQiXCo08S54bWqnE03LazUjCfLhHCnpcXr4jhNMPy5lkz i6UrWrQuopFM0OLQN+IB/G79nsHr0AWnSFgT/WIk= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:18 +0900 Message-Id: <20200709132835.112593-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 06/23] libcamera: PixelFormatInfo: Add functions stride and frameSize 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add member functions to PixelFormatInfo for calculating stride and frame size. This will simplify existing code that calculates these things. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v5: - changed default align parameter for stride() to 1 - added align parameter to frameSize() Changes in v4: - add overloaded frameSize() that takes array of strides - add optional parameter to stride() for byte alignment Changes in v3: - rename functions to stride and frameSize, from bytesPerLine and imageSize, respectively Changes in v2: - make these functions const - add documentation - inline DIV_ROUND_UP --- include/libcamera/internal/formats.h | 6 +++ src/libcamera/formats.cpp | 80 ++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index 211da4a..cad41ad 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -53,6 +53,12 @@ public: static const PixelFormatInfo &info(const PixelFormat &format); static const PixelFormatInfo &info(const V4L2PixelFormat &format); + unsigned int stride(unsigned int width, unsigned int plane, + unsigned int align = 1) const; + unsigned int frameSize(const Size &size, unsigned int align = 1) const; + unsigned int frameSize(const Size &size, + const std::array &strides) const; + /* \todo Add support for non-contiguous memory planes */ const char *name; PixelFormat format; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index 6d96055..0f71061 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -732,4 +732,84 @@ const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format) return info->second; } +/** + * \brief Compute the stride + * \param[in] width The width of the line, in pixels + * \param[in] plane The index of the plane whose stride is to be computed + * \param[in] align The number of bytes to align to (1 for default alignment) + * \return The number of bytes necessary to store a line, or 0 if the + * PixelFormatInfo instance or the \a plane is not valid + */ +unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane, + unsigned int align) const +{ + if (!isValid()) { + LOG(Formats, Warning) << "Invalid pixel format, stride is zero"; + return 0; + } + + if (plane > planes.size() || !planes[plane].bytesPerGroup) { + LOG(Formats, Warning) << "Invalid plane index, stride is zero"; + return 0; + } + + /* ceil(width / pixelsPerGroup) * bytesPerGroup */ + unsigned int stride = (width + pixelsPerGroup - 1) / pixelsPerGroup + * planes[plane].bytesPerGroup; + + /* ceil(stride / align) * align */ + return (stride + align - 1) / align * align; +} + +/** + * \brief Compute the number of bytes necessary to store a frame + * \param[in] size The size of the frame, in pixels + * \param[in] align The number of bytes to align to (1 for default alignment) + * \return The number of bytes necessary to store the frame, or 0 if the + * PixelFormatInfo instance is not valid + */ +unsigned int PixelFormatInfo::frameSize(const Size &size, unsigned int align) const +{ + /* stride * ceil(height / verticalSubSampling) */ + unsigned int sum = 0; + for (unsigned int i = 0; i < 3; i++) { + unsigned int vertSubSample = planes[i].verticalSubSampling; + if (!vertSubSample) + continue; + sum += stride(size.width, i, align) + * ((size.height + vertSubSample - 1) / vertSubSample); + } + + return sum; +} + +/** + * \brief Compute the number of bytes necessary to store a frame + * \param[in] size The size of the frame, in pixels + * \param[in] strides The strides to use for each plane + * + * This function is an overloaded version that takes custom strides for each + * plane, to be used when the device has custom alignment constraints that + * can't be described by just an alignment value. + * + * \return The number of bytes necessary to store the frame, or 0 if the + * PixelFormatInfo instance is not valid + */ +unsigned int +PixelFormatInfo::frameSize(const Size &size, + const std::array &strides) const +{ + /* stride * ceil(height / verticalSubSampling) */ + unsigned int sum = 0; + for (unsigned int i = 0; i < 3; i++) { + unsigned int vertSubSample = planes[i].verticalSubSampling; + if (!vertSubSample) + continue; + sum += strides[i] + * ((size.height + vertSubSample - 1) / vertSubSample); + } + + return sum; +} + } /* namespace libcamera */ From patchwork Thu Jul 9 13:28:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8722 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 20791BD792 for ; Thu, 9 Jul 2020 13:29:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E291A61218; Thu, 9 Jul 2020 15:29:08 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PR4xlM9Y"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6B89261184 for ; Thu, 9 Jul 2020 15:29:07 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E1B20525; Thu, 9 Jul 2020 15:29:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301346; bh=t8gZp024dC8J0AIYMufe0D//whn9nWUHr9DO9Zxkwc4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PR4xlM9YvSlhGw5Y4jusXuUmwvQ3Y7nt6l1a2KofT4LFE4V631foQwi7QzrAfK5nd vlGUv9kxFjA9QloVb1wqWiMUYYjk+RUEMawKRDkMo16cPEKJMA8mY1yRVLe3zpQVBv f+7sFAEfi2ydTXnVzT1YyxL1uxzGNF9eHL/7d7fU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:19 +0900 Message-Id: <20200709132835.112593-8-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 07/23] libcamera: pipeline: raspberrypi: Simplify format fetching 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Simplify code for looking up PixelFormatInfo using a V4L2 format by using the new PixelFormatInfo lookup function based on V4L2 format. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v5 No change in v4 No change in v3 Changes in v2: - just a few words in the commit message --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index f4966f8..1c0000b 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -81,8 +81,7 @@ V4L2DeviceFormat findBestMode(V4L2PixFmtMap &formatsMap, const Size &req) /* Calculate the closest/best mode from the user requested size. */ for (const auto &iter : formatsMap) { V4L2PixelFormat v4l2Format = iter.first; - PixelFormat pixelFormat = v4l2Format.toPixelFormat(); - const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat); + const PixelFormatInfo &info = PixelFormatInfo::info(v4l2Format); for (const SizeRange &sz : iter.second) { double modeWidth = sz.contains(req) ? req.width : sz.max.width; From patchwork Thu Jul 9 13:28:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8723 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 81EB5BD792 for ; Thu, 9 Jul 2020 13:29:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5356E61243; Thu, 9 Jul 2020 15:29:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="YEO3LRE1"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A1B7561184 for ; Thu, 9 Jul 2020 15:29:09 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D5477525; Thu, 9 Jul 2020 15:29:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301349; bh=R2iSmPTEfoknLFVV/rFDTKdJR9G+XRZE2SKRfmh0p8s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YEO3LRE1J5BaLDpHkWkgqquhQAddUNxilpgvZ0t2sKDYsSbk2+djTdS/rHDXx+jGv rUqgIzDr89VO0u+sLHig6BoVlWoQ0pyHGVboZ+4p19oIFWBxQYkc1rMKpq/8EEHbDX gaL/nfwKn5n0VHOUta26VjvBMk1Nc+iz6SIQ6aw8= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:20 +0900 Message-Id: <20200709132835.112593-9-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 08/23] libcamera: pipeline: raspberrypi: Acquire media devices with acquireMediaDevice 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Media devices should be acquired by pipeline handlers via PipelineHandler::acquireMediaDevice so that the media devices can be registered in the pipeline handler so that they can be automatically added to the devnum map for the v4l2 compatibility layer to use. Make the raspberrypi pipeline handler do this. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v5 No change in v4 No change in v3 --- .../pipeline/raspberrypi/raspberrypi.cpp | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 1c0000b..cbb6f1c 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -374,7 +374,6 @@ class PipelineHandlerRPi : public PipelineHandler { public: PipelineHandlerRPi(CameraManager *manager); - ~PipelineHandlerRPi(); CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override; int configure(Camera *camera, CameraConfiguration *config) override; @@ -401,8 +400,8 @@ private: int prepareBuffers(Camera *camera); void freeBuffers(Camera *camera); - std::shared_ptr unicam_; - std::shared_ptr isp_; + MediaDevice *unicam_; + MediaDevice *isp_; }; RPiCameraConfiguration::RPiCameraConfiguration(const RPiCameraData *data) @@ -502,15 +501,6 @@ PipelineHandlerRPi::PipelineHandlerRPi(CameraManager *manager) { } -PipelineHandlerRPi::~PipelineHandlerRPi() -{ - if (unicam_) - unicam_->release(); - - if (isp_) - isp_->release(); -} - CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, const StreamRoles &roles) { @@ -895,17 +885,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator) isp.add("bcm2835-isp0-capture2"); /* Output 1 */ isp.add("bcm2835-isp0-capture3"); /* Stats */ - unicam_ = enumerator->search(unicam); + unicam_ = acquireMediaDevice(enumerator, unicam); if (!unicam_) return false; - isp_ = enumerator->search(isp); + isp_ = acquireMediaDevice(enumerator, isp); if (!isp_) return false; - unicam_->acquire(); - isp_->acquire(); - std::unique_ptr data = std::make_unique(this); /* Locate and open the unicam video streams. */ From patchwork Thu Jul 9 13:28:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8724 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 058DDBD792 for ; Thu, 9 Jul 2020 13:29:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C409B61221; Thu, 9 Jul 2020 15:29:12 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KpTlZn17"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DF383611BA for ; Thu, 9 Jul 2020 15:29:11 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 238C8525; Thu, 9 Jul 2020 15:29:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301351; bh=SZ6JKm2SfkqebE7nZSCnGt56qj/+Uqx9h2hx8UxIjds=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KpTlZn17SKPylTy6xtuXExzTp+rvuHhemjm0hdsrZ4lSRq9st2+IaC7O67ZoCr+5j LIPtwN7MveDVq6OsgG3lb5WelLCXNBIy8HICxtPEcEaj7WxXgYkNti0ffOGOh0a1O/ 6hgcdNM96UCX0yTI+7Bms1ov8yFZRjweXCYFwNXc= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:21 +0900 Message-Id: <20200709132835.112593-10-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 09/23] libcamera: pipeline_handler: Fatal if registering camera without media devices 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Pipeline handlers must acquire media devices via PipelineHander::acquireMediaDevice so that the media devices can be registered with the pipeline handler, so that they can be automatically added to the devnum map for the v4l2 compatibility layer to use. Die fatally if any camera trying to be registered has not acquired any media devices via acquireMediaDevice. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v5 Cosmetic change in v4 No change in v3 --- src/libcamera/pipeline_handler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index de5ca09..ccd45ed 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -496,6 +496,10 @@ void PipelineHandler::registerCamera(std::shared_ptr camera, cameraData_[camera.get()] = std::move(data); cameras_.push_back(camera); + if (mediaDevices_.empty()) + LOG(Pipeline, Fatal) + << "Registering camera with no media devices!"; + /* * Walk the entity list and map the devnums of all capture video nodes * to the camera. From patchwork Thu Jul 9 13:28:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8725 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 79D69BD792 for ; Thu, 9 Jul 2020 13:29:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 45BF1611BA; Thu, 9 Jul 2020 15:29:16 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="IvDTQCVt"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 31A7861184 for ; Thu, 9 Jul 2020 15:29:14 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 61826525; Thu, 9 Jul 2020 15:29:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301353; bh=u09l7K9pwnR7PbnwEbP4TQQ+9RS3agnCH2OAV8C1hvg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IvDTQCVts7S66Q6r+RywnmMvMCvnR1YfMES3DDdLR+KfxqMWAyT8/h/+MYBh7DZ9c N5INnYdkZZZEDMMgwpxq5BhgclmXmT6PSJgvi4Cs62s2zObtAQ48s9HWvyCw9GNwSd 318Dc81E9U/zrfe8Xy9buFfTradLrPtF8QaXtliQ= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:22 +0900 Message-Id: <20200709132835.112593-11-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 10/23] libcamera: pipeline: raspberrypi: Filter out unsupported formats 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Unsupported formats should not be added to the configuration when generating the configuration. Filter them out. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v5 Cosmetic change in v4 No change in v3 --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index cbb6f1c..1822ac9 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -569,13 +569,11 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, /* Translate the V4L2PixelFormat to PixelFormat. */ std::map> deviceFormats; - std::transform(fmts.begin(), fmts.end(), std::inserter(deviceFormats, deviceFormats.end()), - [&](const decltype(fmts)::value_type &format) { - return decltype(deviceFormats)::value_type{ - format.first.toPixelFormat(), - format.second - }; - }); + for (const auto &format : fmts) { + PixelFormat pixelFormat = format.first.toPixelFormat(); + if (pixelFormat.isValid()) + deviceFormats[pixelFormat] = format.second; + } /* Add the stream format based on the device node used for the use case. */ StreamFormats formats(deviceFormats); From patchwork Thu Jul 9 13:28:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8726 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C92BEBD792 for ; Thu, 9 Jul 2020 13:29:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 974EE61245; Thu, 9 Jul 2020 15:29:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="hT6Qkekq"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id ABDA161184 for ; Thu, 9 Jul 2020 15:29:16 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9F44D525; Thu, 9 Jul 2020 15:29:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301356; bh=TTTavKx10wmrItOLi3m3vK+XqIswj6YA7ZO/tgyT6iU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hT6Qkekqfxsfo9DuCmrXIqmeE3O2vXHc/pbIJFA/JbNIFxeThcjPxL6DUshI1bn9+ oKMjEYSJOKF2vIIaB2F5Ar6J82K7YY2fhDEgFmxTmO8OK14+pdrfaZCvFEI0l5yNMZ kJRtnhyiFIC2J6CeaYis+kQx3lWLYPoIDe/hV9Ok= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:23 +0900 Message-Id: <20200709132835.112593-12-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 11/23] libcamera: pipeline: uvcvideo: Filter out unsupported formats 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Unsupported formats should not be added to the configuration when generating the configuration. Filter them out. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- No change in v5 Cosmetic change in v4 No change in v3 --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 80a0e77..9db69dd 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -161,14 +161,11 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera, std::map> v4l2Formats = data->video_->formats(); std::map> deviceFormats; - std::transform(v4l2Formats.begin(), v4l2Formats.end(), - std::inserter(deviceFormats, deviceFormats.begin()), - [&](const decltype(v4l2Formats)::value_type &format) { - return decltype(deviceFormats)::value_type{ - format.first.toPixelFormat(), - format.second - }; - }); + for (const auto &format : v4l2Formats) { + PixelFormat pixelFormat = format.first.toPixelFormat(); + if (pixelFormat.isValid()) + deviceFormats[pixelFormat] = format.second; + } StreamFormats formats(deviceFormats); StreamConfiguration cfg(formats); From patchwork Thu Jul 9 13:28:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8727 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 2C9BFBD792 for ; Thu, 9 Jul 2020 13:29:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EF5ED61221; Thu, 9 Jul 2020 15:29:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ozBd2D5b"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 13B7361184 for ; Thu, 9 Jul 2020 15:29:19 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 33DA1525; Thu, 9 Jul 2020 15:29:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301358; bh=WJQYWIR9dO09qEADGTKWs1L3C0eGUVRmmPPR/vrM8bo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ozBd2D5bb2X68P0JucNyoptP2BV7BMxjyb7Oyanf85WLpp5z18uR+6qOVMkn1EbX0 M0qAuMnchMLxOoAZgMOKc1oeCH3CW+cM7YvRbv+M+kMnCcDzCZyRodYoUou2M3fWCP 4WXgLxRTWZlMQc3CZ/10D+L4CsWlfxSloLM0B0+g= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:24 +0900 Message-Id: <20200709132835.112593-13-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 12/23] libcamera: ipu3: Fill stride and frameSize at config validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fill the stride and frameSize fields of the StreamConfiguration at configuration validation time instead of at camera configuration time. This allows applications to get the stride when trying a configuration without modifying the active configuration of the camera. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v5: - simplify code Changes in v4: - fix stride and frameSize calculation - mention motivation in commit message New in v3 --- src/libcamera/pipeline/ipu3/ipu3.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index af51fb2..eb00eec 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -278,6 +278,12 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() << cfg.toString(); status = Adjusted; } + + const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); + bool packedRaw = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; + + cfg.stride = info.stride(cfg.size.width, 0, packedRaw ? 64 : 1); + cfg.frameSize = info.frameSize(cfg.size, packedRaw ? 64 : 1); } return status; @@ -495,21 +501,13 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) if (ret) return ret; - cfg.stride = outputFormat.planes[0].bpl; outActive = true; } else if (stream == vfStream) { ret = imgu->configureViewfinder(cfg, &outputFormat); if (ret) return ret; - cfg.stride = outputFormat.planes[0].bpl; vfActive = true; - } else { - /* - * The RAW stream is configured as part of the CIO2 and - * no configuration is needed for the ImgU. - */ - cfg.stride = cio2Format.planes[0].bpl; } } From patchwork Thu Jul 9 13:28:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8728 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 988BFBD792 for ; Thu, 9 Jul 2020 13:29:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6666E61218; Thu, 9 Jul 2020 15:29:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="TECbZkSH"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 100C661243 for ; Thu, 9 Jul 2020 15:29:21 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8AA56525; Thu, 9 Jul 2020 15:29:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301360; bh=EXuaUjfqdW0vH+xE8/bLlGW5Wr9ixh4D3YtVQ3EAfZ8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TECbZkSH2rHTxOYTnqIeWsUskswUCR6t9EOInpAbk1nOsbbRrvMWElPYLiOpyEfrz zyhE9SVxYuQxsckYRve4MxHLKRBXIrA7/JhNlNKlRZbK9k4VOKiEbMLp5ljW9zS+aI 6+uP6rgx69/HISoxon7yKWrN8AVOFDjMs+wVpyNE= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:25 +0900 Message-Id: <20200709132835.112593-14-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 13/23] libcamera: raspberrypi: Fill stride and frameSize at config validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fill the stride and frameSize fields of the StreamConfiguration at configuration validation time instead of at camera configuration time. This allows applications to get the stride when trying a configuration without modifying the active configuration of the camera. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Naushir Patuck --- Changes in v5: - clean up code a bit - move setting default size and width into separate patch Changes in v4: - mention motivation in commit message - also fill stride and frameSize in the default format New in v3 --- .../pipeline/raspberrypi/raspberrypi.cpp | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 1822ac9..a08ad6a 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -427,6 +427,10 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() */ V4L2PixFmtMap fmts = data_->unicam_[Unicam::Image].dev()->formats(); V4L2DeviceFormat sensorFormat = findBestMode(fmts, cfg.size); + int ret = data_->unicam_[Unicam::Image].dev()->tryFormat(&sensorFormat); + if (ret) + return Invalid; + PixelFormat sensorPixFormat = sensorFormat.fourcc.toPixelFormat(); if (cfg.size != sensorFormat.size || cfg.pixelFormat != sensorPixFormat) { @@ -434,6 +438,10 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() cfg.pixelFormat = sensorPixFormat; status = Adjusted; } + + cfg.stride = sensorFormat.planes[0].bpl; + cfg.frameSize = sensorFormat.planes[0].size; + rawCount++; } else { outSize[outCount] = std::make_pair(count, cfg.size); @@ -478,19 +486,34 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() * have that fixed up in the code above. * */ - PixelFormat &cfgPixFmt = config_.at(outSize[i].first).pixelFormat; - V4L2PixFmtMap fmts; + StreamConfiguration &cfg = config_.at(outSize[i].first); + PixelFormat &cfgPixFmt = cfg.pixelFormat; + V4L2VideoDevice *dev; if (i == maxIndex) - fmts = data_->isp_[Isp::Output0].dev()->formats(); + dev = data_->isp_[Isp::Output0].dev(); else - fmts = data_->isp_[Isp::Output1].dev()->formats(); + dev = data_->isp_[Isp::Output1].dev(); + + V4L2PixFmtMap fmts = dev->formats(); if (fmts.find(V4L2PixelFormat::fromPixelFormat(cfgPixFmt, false)) == fmts.end()) { /* If we cannot find a native format, use a default one. */ cfgPixFmt = formats::NV12; status = Adjusted; } + + V4L2DeviceFormat format = {}; + format.fourcc = dev->toV4L2PixelFormat(cfg.pixelFormat); + format.size = cfg.size; + + int ret = dev->tryFormat(&format); + if (ret) + return Invalid; + + cfg.stride = format.planes[0].bpl; + cfg.frameSize = format.planes[0].size; + } return status; @@ -655,7 +678,6 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) if (isRaw(cfg.pixelFormat)) { cfg.setStream(&data->isp_[Isp::Input]); - cfg.stride = sensorFormat.planes[0].bpl; data->isp_[Isp::Input].setExternal(true); continue; } @@ -679,7 +701,6 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) } cfg.setStream(&data->isp_[Isp::Output0]); - cfg.stride = format.planes[0].bpl; data->isp_[Isp::Output0].setExternal(true); } @@ -705,7 +726,6 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) */ if (!cfg.stream()) { cfg.setStream(&data->isp_[Isp::Output1]); - cfg.stride = format.planes[0].bpl; data->isp_[Isp::Output1].setExternal(true); } } From patchwork Thu Jul 9 13:28:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8729 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 0AAACBD792 for ; Thu, 9 Jul 2020 13:29:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CC1DD61214; Thu, 9 Jul 2020 15:29:25 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ReSsM0Yl"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 34B2F61184 for ; Thu, 9 Jul 2020 15:29:24 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7D59B56E; Thu, 9 Jul 2020 15:29:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301362; bh=EMXNuZEE6bh/6i3wipPc7HOgWZjVkxvGkxqN/EFzbMI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ReSsM0Ylm4uG9oLx3GqWuNCp59kRrgWPsXfAgqzJDOo25NLlmo+mKTjdL0J8Xca3D H9q//9MSm9B04t/LRbXR+CkF+sBNCSbhpLxxa2/oMEKqSExRp/ximfQSquqw5xArcs oOBbE0PXwj/agCEyOxX+j8pXpuq0HpN2mKjqbaBU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:26 +0900 Message-Id: <20200709132835.112593-15-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 14/23] libcamera: raspberrypi: Set default configuration size at validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If a native format is not found, a default NV12 format is set. However, this does not set a default configuration size, sometimes resulting in a 0x0 size. Fix this by setting a default configuration size. Signed-off-by: Paul Elder --- New in v5, split from "libcamera: raspberrypi: Fill stride and frameSize at config validation" --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index a08ad6a..5f00500 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -500,6 +500,9 @@ CameraConfiguration::Status RPiCameraConfiguration::validate() if (fmts.find(V4L2PixelFormat::fromPixelFormat(cfgPixFmt, false)) == fmts.end()) { /* If we cannot find a native format, use a default one. */ cfgPixFmt = formats::NV12; + cfg.size.width = 1920; + cfg.size.height = 1080; + status = Adjusted; } From patchwork Thu Jul 9 13:28:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8730 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 70454BD792 for ; Thu, 9 Jul 2020 13:29:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3E73361214; Thu, 9 Jul 2020 15:29:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PoY+nJB2"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B632D61184 for ; Thu, 9 Jul 2020 15:29:26 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A394A56E; Thu, 9 Jul 2020 15:29:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301366; bh=FNKiy0STbJtjjbWrtFa/JquxkdCNS3SZQvVkx9VG9KA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PoY+nJB2B0nsHySh4V77KdaxfxladhJQI58sV7cRCP3zluc0H2T/6JkmBUL6jzzod 0nhZiUY5qEcoHpujK1KtpcZCykfUCPpmA7Tlmsp76m7gODHEAFuhWxFMsdNUTinauK z7djfN5d+SI7xW6TFGrtOgo4Koprm0faPoGJz7YY= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:27 +0900 Message-Id: <20200709132835.112593-16-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 15/23] libcamera: rkisp1: Fill stride and frameSize at config validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fill the stride and frameSize fields of the StreamConfiguration at configuration validation time instead of at camera configuration time. This allows applications to get the stride when trying a configuration without modifying the active configuration of the camera. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v5 Changes in v4: - mention motivation in commit message - get stride and frameSize from tryFormat on the capture video node New in v3 --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 051d77a..7ce4140 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -115,9 +115,9 @@ public: class RkISP1CameraData : public CameraData { public: - RkISP1CameraData(PipelineHandler *pipe) + RkISP1CameraData(PipelineHandler *pipe, V4L2VideoDevice *video) : CameraData(pipe), sensor_(nullptr), frame_(0), - frameInfo_(pipe) + frameInfo_(pipe), video_(video) { } @@ -135,6 +135,8 @@ public: RkISP1Frames frameInfo_; RkISP1Timeline timeline_; + V4L2VideoDevice *video_; + private: void queueFrameAction(unsigned int frame, const IPAOperationData &action); @@ -535,6 +537,17 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() cfg.bufferCount = RKISP1_BUFFER_COUNT; + V4L2DeviceFormat format = {}; + format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.size = cfg.size; + + int ret = data_->video_->tryFormat(&format); + if (ret) + return Invalid; + + cfg.stride = format.planes[0].bpl; + cfg.frameSize = format.planes[0].size; + return status; } @@ -683,7 +696,6 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) return ret; cfg.setStream(&data->stream_); - cfg.stride = outputFormat.planes[0].bpl; return 0; } @@ -934,7 +946,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) int ret; std::unique_ptr data = - std::make_unique(this); + std::make_unique(this, video_); ControlInfoMap::Map ctrls; ctrls.emplace(std::piecewise_construct, From patchwork Thu Jul 9 13:28:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8731 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id CD344BD792 for ; Thu, 9 Jul 2020 13:29:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9CEEF6124D; Thu, 9 Jul 2020 15:29:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="FUAaUp2T"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 150BA61184 for ; Thu, 9 Jul 2020 15:29:29 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0A5D8525; Thu, 9 Jul 2020 15:29:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301368; bh=/nRUNLn4J1x6/qZih/bqQpzsiZ/RvCQCLK51RbG2xG4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FUAaUp2ThlT/rrdeYwewRUkKwfz3NBCnA1dbtAWtkEkVa4qscKyNqN1bXNtp9tEpd eQHXs7pgS46bjcfuDIG9izv87DAKkD1l+cBSof7KSVpAzma81DNR/jljx6pceyaRYr GQySAw/fCS0u1DqkKEh6Qn4Fj3zHhVNgebtGeDww= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:28 +0900 Message-Id: <20200709132835.112593-17-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 16/23] libcamera: simple: Fill stride and frameSize at config validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fill the stride and frameSize fields of the StreamConfiguration at configuration validation time instead of at camera configuration time. This allows applications to get the stride when trying a configuration without modifying the active configuration of the camera. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- Cosmetic change in v5 Changes in v4: - fix converter's stride and frameSize (get it via tryFormat instead of calculation) - merge converter's stride and frameSize to one function - return error if tryFormat fails - mention motivation in commit message New in v3 --- src/libcamera/pipeline/simple/converter.cpp | 19 +++++++++++++++ src/libcamera/pipeline/simple/converter.h | 4 ++++ src/libcamera/pipeline/simple/simple.cpp | 26 +++++++++++++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index e5e2f0f..cef1503 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -261,4 +261,23 @@ void SimpleConverter::outputBufferReady(FrameBuffer *buffer) } } +int SimpleConverter::strideAndFrameSize(const Size &size, + const PixelFormat &pixelFormat, + unsigned int *strideOut, + unsigned int *frameSizeOut) +{ + V4L2DeviceFormat format = {}; + format.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat); + format.size = size; + + int ret = m2m_->capture()->tryFormat(&format); + if (ret < 0) + return -1; + + *strideOut = format.planes[0].bpl; + *frameSizeOut = format.planes[0].size; + + return 0; +} + } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index ef18cf7..3e46988 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -46,6 +46,10 @@ public: int queueBuffers(FrameBuffer *input, FrameBuffer *output); + int strideAndFrameSize(const Size &size, const PixelFormat &pixelFormat, + unsigned int *strideOut, + unsigned int *frameSizeOut); + Signal bufferReady; private: diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 1ec8d0f..2ca57d0 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -457,6 +457,30 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() cfg.bufferCount = 3; + /* Set the stride and frameSize. */ + if (!needConversion_) { + V4L2DeviceFormat format = {}; + format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.size = cfg.size; + + int ret = data_->video_->tryFormat(&format); + if (ret < 0) + return Invalid; + + cfg.stride = format.planes[0].bpl; + cfg.frameSize = format.planes[0].size; + + return status; + } + + SimplePipelineHandler *pipe = static_cast(data_->pipe_); + SimpleConverter *converter = pipe->converter(); + + int ret = converter->strideAndFrameSize(cfg.size, cfg.pixelFormat, + &cfg.stride, &cfg.frameSize); + if (ret < 0) + return Invalid; + return status; } @@ -557,8 +581,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) return -EINVAL; } - cfg.stride = captureFormat.planes[0].bpl; - /* Configure the converter if required. */ useConverter_ = config->needConversion(); From patchwork Thu Jul 9 13:28:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8732 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 5F1FBBD792 for ; Thu, 9 Jul 2020 13:29:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2B8346124B; Thu, 9 Jul 2020 15:29:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="u8r6/3MK"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8A69361184 for ; Thu, 9 Jul 2020 15:29:32 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7A1AB525; Thu, 9 Jul 2020 15:29:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301371; bh=7ItbkN2YboJI0sNfxj84oIS6MRpGo3gx8LbFv/ivkK4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=u8r6/3MKHlZxMbXCR0BjO/Lu3ArqBy+Cq4OYpGlzkG583eU+xQSovAMFO7HgAvnzo Mp4QtxvQHi2MJOZ3rd6e7rYamRI5yGm6yMiag4cWH9byK6kVNlmdLnxIkA7pPt87by gA9D6khWZVaxY25h9tRvIWlm5A6TTygxxaUsTr4c= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:29 +0900 Message-Id: <20200709132835.112593-18-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 17/23] libcamera: uvcvideo: Fill stride and frameSize at config validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fill the stride and frameSize fields of the StreamConfiguration at configuration validation time instead of at camera configuration time. This allows applications to get the stride when trying a configuration without modifying the active configuration of the camera. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- No change in v5 Changes in v4: - return error if tryFormat fails - pass UVCCameraData to UVCCameraConfiguration, instead of V4l2VideoDevice - mention motivation in commit message New in v3 --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 23 +++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 9db69dd..47f383d 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -53,9 +53,12 @@ public: class UVCCameraConfiguration : public CameraConfiguration { public: - UVCCameraConfiguration(); + UVCCameraConfiguration(UVCCameraData *data); Status validate() override; + +private: + UVCCameraData *data_; }; class PipelineHandlerUVC : public PipelineHandler @@ -89,8 +92,8 @@ private: } }; -UVCCameraConfiguration::UVCCameraConfiguration() - : CameraConfiguration() +UVCCameraConfiguration::UVCCameraConfiguration(UVCCameraData *data) + : CameraConfiguration(), data_(data) { } @@ -141,6 +144,17 @@ CameraConfiguration::Status UVCCameraConfiguration::validate() cfg.bufferCount = 4; + V4L2DeviceFormat format = {}; + format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.size = cfg.size; + + int ret = data_->video_->tryFormat(&format); + if (ret) + return Invalid; + + cfg.stride = format.planes[0].bpl; + cfg.frameSize = format.planes[0].size; + return status; } @@ -153,7 +167,7 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera, const StreamRoles &roles) { UVCCameraData *data = cameraData(camera); - CameraConfiguration *config = new UVCCameraConfiguration(); + CameraConfiguration *config = new UVCCameraConfiguration(data); if (roles.empty()) return config; @@ -200,7 +214,6 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config) return -EINVAL; cfg.setStream(&data->stream_); - cfg.stride = format.planes[0].bpl; return 0; } From patchwork Thu Jul 9 13:28:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8733 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A3998BD792 for ; Thu, 9 Jul 2020 13:29:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7532F6124B; Thu, 9 Jul 2020 15:29:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="MHuzHhZU"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 25AE261221 for ; Thu, 9 Jul 2020 15:29:34 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0EB2256E; Thu, 9 Jul 2020 15:29:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301373; bh=lBWix7yc5EXSZhGovCTld2c/XeOtoiS3mUXaVikjxAU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MHuzHhZUFhR2Dq1YTzKQm3kJKXbqIVwWRpfFOaY+6U15/IRLmCTttZLSvmT5RPB/j 0T1fRHkmMyYCSoP1ocHHy4MaazSf+sqiz/mv+PqIrMXsfa2q6AqUVmXioO+3kFZS8Z Q456rP9cjx/z1tNgEXZh7ngISpfKZ7u4fXEF+iIo= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:30 +0900 Message-Id: <20200709132835.112593-19-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 18/23] libcamera: vimc: Fill stride and frameSize at config validation 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Fill the stride and frameSize fields of the StreamConfiguration at configuration validation time instead of at camera configuration time. This allows applications to get the stride when trying a configuration without modifying the active configuration of the camera. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- No change in v5 Changes in v4: - mention motivation in commit message - get stride and frameSize from tryFormat on capture video node New in v3 --- src/libcamera/pipeline/vimc/vimc.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index b653066..a6f457c 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -72,9 +72,12 @@ public: class VimcCameraConfiguration : public CameraConfiguration { public: - VimcCameraConfiguration(); + VimcCameraConfiguration(VimcCameraData *data); Status validate() override; + +private: + VimcCameraData *data_; }; class PipelineHandlerVimc : public PipelineHandler @@ -115,8 +118,8 @@ static const std::map pixelformats{ } /* namespace */ -VimcCameraConfiguration::VimcCameraConfiguration() - : CameraConfiguration() +VimcCameraConfiguration::VimcCameraConfiguration(VimcCameraData *data) + : CameraConfiguration(), data_(data) { } @@ -160,6 +163,17 @@ CameraConfiguration::Status VimcCameraConfiguration::validate() cfg.bufferCount = 4; + V4L2DeviceFormat format = {}; + format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.size = cfg.size; + + int ret = data_->video_->tryFormat(&format); + if (ret) + return Invalid; + + cfg.stride = format.planes[0].bpl; + cfg.frameSize = format.planes[0].size; + return status; } @@ -171,8 +185,8 @@ PipelineHandlerVimc::PipelineHandlerVimc(CameraManager *manager) CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera, const StreamRoles &roles) { - CameraConfiguration *config = new VimcCameraConfiguration(); VimcCameraData *data = cameraData(camera); + CameraConfiguration *config = new VimcCameraConfiguration(data); if (roles.empty()) return config; @@ -282,7 +296,6 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config) return ret; cfg.setStream(&data->stream_); - cfg.stride = format.planes[0].bpl; return 0; } From patchwork Thu Jul 9 13:28:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8734 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 03A71BD792 for ; Thu, 9 Jul 2020 13:29:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C48876124F; Thu, 9 Jul 2020 15:29:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="eCOLanQJ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C96C8611BA for ; Thu, 9 Jul 2020 15:29:36 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 977099CC; Thu, 9 Jul 2020 15:29:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301376; bh=u9MOtYm3vp3VxRbxe4jjmWJ4cEoRr7b/itCNiX0RisU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eCOLanQJn5/KQpYZzwxA5IxPt6bhrfcQNE9gCQGY7TpIJjgiLyS6H6uAlMPUjRMk1 qMsWU8n89l/xT5aFTBsHlqj1zHWIEv0GCXwbxn2h8QDbgH1L/0hXYSzdRSkF/3Ngaf 5P2hBpqXEAl3xLUaO6JQYRqGwEszcuQJ2OJM5Y+k= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:31 +0900 Message-Id: <20200709132835.112593-20-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 19/23] libcamera: StreamConfiguration: Update stride 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that all the pipeline handlers fill in the stride information at validation time, update the documentation accordingly. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- No change in v5 No change in v4 New in v3 --- src/libcamera/stream.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index 6d6e279..d5da834 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -309,11 +309,8 @@ StreamConfiguration::StreamConfiguration(const StreamFormats &formats) * * The stride value reports the number of bytes between the beginning of * successive lines in an image buffer for this stream. The value is - * valid after successfully configuring the camera with this - * configuration with a call to Camera::Configure(). - * - * \todo Update this value when configuration is validated instead of when - * the camera is configured. + * valid after successfully validating the configuration with a call to + * CameraConfiguration::validate(). */ /** From patchwork Thu Jul 9 13:28:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8735 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 54B5BBD792 for ; Thu, 9 Jul 2020 13:29:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2187B611BA; Thu, 9 Jul 2020 15:29:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="M5Ee6Eq3"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DEC06611BA for ; Thu, 9 Jul 2020 15:29:39 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 33DC256E; Thu, 9 Jul 2020 15:29:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301379; bh=dtc2+Z8g+ODJm3FVyETwxgyoQyMsa22bFPLH4RYBYpE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M5Ee6Eq3GLeeir6VaQ35CtNvtaJII6lsD2sdKks+Cj+4wv9J+9tqYXGh6ZxD5cWCI OW82POgkuM7uOX/3/cWdDHUvPGMM45UgeajxuFPRFE0k5Bo/f25xhGxEFBphxZxEe6 OUNLlnKmgpmgztz37nPajO1puaUV5/nDodOVUGSc= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:32 +0900 Message-Id: <20200709132835.112593-21-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 20/23] v4l2: v4l2_camera: Fix stream selection for buffer operations 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The buffer operations in V4L2Camera were getting the stream from the wrong place. Fix it. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- No change in v5 New in v4 --- src/v4l2/v4l2_camera.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index ffc1230..a923256 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -140,7 +140,7 @@ int V4L2Camera::configure(StreamConfiguration *streamConfigOut, int V4L2Camera::allocBuffers(unsigned int count) { - Stream *stream = *camera_->streams().begin(); + Stream *stream = config_->at(0).stream(); return bufferAllocator_->allocate(stream); } @@ -149,13 +149,13 @@ void V4L2Camera::freeBuffers() { pendingRequests_.clear(); - Stream *stream = *camera_->streams().begin(); + Stream *stream = config_->at(0).stream(); bufferAllocator_->free(stream); } FileDescriptor V4L2Camera::getBufferFd(unsigned int index) { - Stream *stream = *camera_->streams().begin(); + Stream *stream = config_->at(0).stream(); const std::vector> &buffers = bufferAllocator_->buffers(stream); From patchwork Thu Jul 9 13:28:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8736 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id AA763BD792 for ; Thu, 9 Jul 2020 13:29:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 75B3A61221; Thu, 9 Jul 2020 15:29:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Cd7hqkGp"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1A2CB611B2 for ; Thu, 9 Jul 2020 15:29:42 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 57388525; Thu, 9 Jul 2020 15:29:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301381; bh=7e6M4KlbB2BYinqhHdcUpbtkt7X6HUVNLkaQlbvcLqA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cd7hqkGpC5ETw2h63hdvhEZbarDZbvu+rDWXJo0csQW/qlPb2QmVdOdSW/1GUWttz s+CxmziLWVybs9YM2OOzh6cZ8nn8v/B1XIQU6Oa1PtQtnPB75BcfO9BcAYlmzPYwkI ctHUx/sAzK2a/GltMx/BQzf6e/loyJ9EjRuiby8w= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:33 +0900 Message-Id: <20200709132835.112593-22-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 21/23] v4l2: v4l2_camera_proxy: Get stride and frameSize from stream config 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The stride and frameSize should be obtained through StreamConfiguration rather than PixelFormatInfo, as pipeline handlers might have different values (eg. for alignment). Get the stride and frameSize values from StreamConfiguration instead of from PixelFormatInfo. This removes the need for V4L2CameraProxy's calculation helper functions (bplMultiplier, imageSize, v4l2ToDrm, drmToV4L2, calculateSizeImage) and formats, so remove them. This also removes the need for V4L2CameraProxy::calculateSizeImage, so remove it,. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v5: - fix rebase error Changes in v4: - squashed with "v4l2: v4l2_camera_proxy: Use libcamera formats" New in v3 --- src/v4l2/v4l2_camera_proxy.cpp | 192 ++++++--------------------------- src/v4l2/v4l2_camera_proxy.h | 8 -- 2 files changed, 32 insertions(+), 168 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index c246570..8c55a06 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -20,6 +20,7 @@ #include #include +#include "libcamera/internal/formats.h" #include "libcamera/internal/log.h" #include "libcamera/internal/utils.h" @@ -70,7 +71,6 @@ int V4L2CameraProxy::open(V4L2CameraFile *file) vcam_->getStreamConfig(&streamConfig_); setFmtFromConfig(streamConfig_); - sizeimage_ = calculateSizeImage(streamConfig_); files_.insert(file); @@ -164,33 +164,22 @@ bool V4L2CameraProxy::validateMemoryType(uint32_t memory) void V4L2CameraProxy::setFmtFromConfig(StreamConfiguration &streamConfig) { - curV4L2Format_.fmt.pix.width = streamConfig.size.width; - curV4L2Format_.fmt.pix.height = streamConfig.size.height; - curV4L2Format_.fmt.pix.pixelformat = drmToV4L2(streamConfig.pixelFormat); - curV4L2Format_.fmt.pix.field = V4L2_FIELD_NONE; - curV4L2Format_.fmt.pix.bytesperline = - bplMultiplier(curV4L2Format_.fmt.pix.pixelformat) * - curV4L2Format_.fmt.pix.width; - curV4L2Format_.fmt.pix.sizeimage = - imageSize(curV4L2Format_.fmt.pix.pixelformat, - curV4L2Format_.fmt.pix.width, - curV4L2Format_.fmt.pix.height); - curV4L2Format_.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; - curV4L2Format_.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - curV4L2Format_.fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + const PixelFormatInfo &info = PixelFormatInfo::info(streamConfig.pixelFormat); + Size size = streamConfig.size; + + curV4L2Format_.fmt.pix.width = size.width; + curV4L2Format_.fmt.pix.height = size.height; + curV4L2Format_.fmt.pix.pixelformat = info.v4l2Format; + curV4L2Format_.fmt.pix.field = V4L2_FIELD_NONE; + curV4L2Format_.fmt.pix.bytesperline = streamConfig.stride; + curV4L2Format_.fmt.pix.sizeimage = streamConfig.frameSize; + curV4L2Format_.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + curV4L2Format_.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + curV4L2Format_.fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; curV4L2Format_.fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; - curV4L2Format_.fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; -} + curV4L2Format_.fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; -unsigned int V4L2CameraProxy::calculateSizeImage(StreamConfiguration &streamConfig) -{ - /* - * \todo Merge this method with setFmtFromConfig (need imageSize to - * support all libcamera formats first, or filter out MJPEG for now). - */ - return imageSize(drmToV4L2(streamConfig.pixelFormat), - streamConfig.size.width, - streamConfig.size.height); + sizeimage_ = streamConfig.frameSize; } void V4L2CameraProxy::querycap(std::shared_ptr camera) @@ -253,12 +242,13 @@ int V4L2CameraProxy::vidioc_enum_framesizes(V4L2CameraFile *file, struct v4l2_fr { LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_framesizes fd = " << file->efd(); - PixelFormat argFormat = v4l2ToDrm(arg->pixel_format); + V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->pixel_format); + PixelFormat format = PixelFormatInfo::info(v4l2Format).format; /* * \todo This might need to be expanded as few pipeline handlers * report StreamFormats. */ - const std::vector &frameSizes = streamConfig_.formats().sizes(argFormat); + const std::vector &frameSizes = streamConfig_.formats().sizes(format); if (arg->index >= frameSizes.size()) return -EINVAL; @@ -279,12 +269,14 @@ int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc * arg->index >= streamConfig_.formats().pixelformats().size()) return -EINVAL; + PixelFormat format = streamConfig_.formats().pixelformats()[arg->index]; + /* \todo Set V4L2_FMT_FLAG_COMPRESSED for compressed formats. */ arg->flags = 0; /* \todo Add map from format to description. */ utils::strlcpy(reinterpret_cast(arg->description), "Video Format Description", sizeof(arg->description)); - arg->pixelformat = drmToV4L2(streamConfig_.formats().pixelformats()[arg->index]); + arg->pixelformat = PixelFormatInfo::info(format).v4l2Format; memset(arg->reserved, 0, sizeof(arg->reserved)); @@ -306,7 +298,8 @@ int V4L2CameraProxy::vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg) void V4L2CameraProxy::tryFormat(struct v4l2_format *arg) { - PixelFormat format = v4l2ToDrm(arg->fmt.pix.pixelformat); + V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat); + PixelFormat format = PixelFormatInfo::info(v4l2Format).format; const std::vector &formats = streamConfig_.formats().pixelformats(); if (std::find(formats.begin(), formats.end(), format) == formats.end()) @@ -317,15 +310,14 @@ void V4L2CameraProxy::tryFormat(struct v4l2_format *arg) if (std::find(sizes.begin(), sizes.end(), size) == sizes.end()) size = streamConfig_.formats().sizes(format)[0]; + const PixelFormatInfo &formatInfo = PixelFormatInfo::info(format); + arg->fmt.pix.width = size.width; arg->fmt.pix.height = size.height; - arg->fmt.pix.pixelformat = drmToV4L2(format); + arg->fmt.pix.pixelformat = formatInfo.v4l2Format; arg->fmt.pix.field = V4L2_FIELD_NONE; - arg->fmt.pix.bytesperline = bplMultiplier(drmToV4L2(format)) * - arg->fmt.pix.width; - arg->fmt.pix.sizeimage = imageSize(drmToV4L2(format), - arg->fmt.pix.width, - arg->fmt.pix.height); + arg->fmt.pix.bytesperline = formatInfo.stride(size.width, 0); + arg->fmt.pix.sizeimage = formatInfo.frameSize(size); arg->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; arg->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; arg->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; @@ -350,18 +342,13 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) tryFormat(arg); Size size(arg->fmt.pix.width, arg->fmt.pix.height); + V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat); ret = vcam_->configure(&streamConfig_, size, - v4l2ToDrm(arg->fmt.pix.pixelformat), + PixelFormatInfo::info(v4l2Format).format, bufferCount_); if (ret < 0) return -EINVAL; - unsigned int sizeimage = calculateSizeImage(streamConfig_); - if (sizeimage == 0) - return -EINVAL; - - sizeimage_ = sizeimage; - setFmtFromConfig(streamConfig_); return 0; @@ -495,27 +482,13 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf freeBuffers(); Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height); + V4L2PixelFormat v4l2Format = V4L2PixelFormat(curV4L2Format_.fmt.pix.pixelformat); int ret = vcam_->configure(&streamConfig_, size, - v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), + PixelFormatInfo::info(v4l2Format).format, arg->count); if (ret < 0) return -EINVAL; - sizeimage_ = calculateSizeImage(streamConfig_); - /* - * If we return -EINVAL here then the application will think that we - * don't support streaming mmap. Since we don't support readwrite and - * userptr either, the application will get confused and think that - * we don't support anything. - * On the other hand, if the set format at the time of reqbufs has a - * zero sizeimage we'll get a floating point exception when we try to - * stream it. - */ - if (sizeimage_ == 0) - LOG(V4L2Compat, Warning) - << "sizeimage of at least one format is zero. " - << "Streaming this format will cause a floating point exception."; - setFmtFromConfig(streamConfig_); arg->count = streamConfig_.bufferCount; @@ -835,104 +808,3 @@ void V4L2CameraProxy::release(V4L2CameraFile *file) owner_ = nullptr; } - -struct PixelFormatPlaneInfo { - unsigned int bitsPerPixel; - unsigned int hSubSampling; - unsigned int vSubSampling; -}; - -struct PixelFormatInfo { - PixelFormat format; - uint32_t v4l2Format; - unsigned int numPlanes; - std::array planes; -}; - -namespace { - -static const std::array pixelFormatInfo = {{ - /* RGB formats. */ - { formats::RGB888, V4L2_PIX_FMT_BGR24, 1, {{ { 24, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - { formats::BGR888, V4L2_PIX_FMT_RGB24, 1, {{ { 24, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - { formats::BGRA8888, V4L2_PIX_FMT_ARGB32, 1, {{ { 32, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - /* YUV packed formats. */ - { formats::UYVY, V4L2_PIX_FMT_UYVY, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - { formats::VYUY, V4L2_PIX_FMT_VYUY, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - { formats::YUYV, V4L2_PIX_FMT_YUYV, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - { formats::YVYU, V4L2_PIX_FMT_YVYU, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, - /* YUY planar formats. */ - { formats::NV12, V4L2_PIX_FMT_NV12, 2, {{ { 8, 1, 1 }, { 16, 2, 2 }, { 0, 0, 0 } }} }, - { formats::NV21, V4L2_PIX_FMT_NV21, 2, {{ { 8, 1, 1 }, { 16, 2, 2 }, { 0, 0, 0 } }} }, - { formats::NV16, V4L2_PIX_FMT_NV16, 2, {{ { 8, 1, 1 }, { 16, 2, 1 }, { 0, 0, 0 } }} }, - { formats::NV61, V4L2_PIX_FMT_NV61, 2, {{ { 8, 1, 1 }, { 16, 2, 1 }, { 0, 0, 0 } }} }, - { formats::NV24, V4L2_PIX_FMT_NV24, 2, {{ { 8, 1, 1 }, { 16, 1, 1 }, { 0, 0, 0 } }} }, - { formats::NV42, V4L2_PIX_FMT_NV42, 2, {{ { 8, 1, 1 }, { 16, 1, 1 }, { 0, 0, 0 } }} }, - { formats::YUV420, V4L2_PIX_FMT_YUV420, 3, {{ { 8, 1, 1 }, { 8, 2, 2 }, { 8, 2, 2 } }} }, - { formats::YUV422, V4L2_PIX_FMT_YUV422P, 3, {{ { 8, 1, 1 }, { 8, 2, 1 }, { 8, 2, 1 } }} }, - /* Compressed formats. */ - /* - * \todo Get a better image size estimate for MJPEG, via - * StreamConfiguration, instead of using the worst-case - * width * height * bpp of uncompressed data. - */ - { formats::MJPEG, V4L2_PIX_FMT_MJPEG, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} }, -}}; - -} /* namespace */ - -/* \todo make libcamera export these */ -unsigned int V4L2CameraProxy::bplMultiplier(uint32_t format) -{ - auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), - [format](const PixelFormatInfo &info) { - return info.v4l2Format == format; - }); - if (info == pixelFormatInfo.end()) - return 0; - - return info->planes[0].bitsPerPixel / 8; -} - -unsigned int V4L2CameraProxy::imageSize(uint32_t format, unsigned int width, - unsigned int height) -{ - auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), - [format](const PixelFormatInfo &info) { - return info.v4l2Format == format; - }); - if (info == pixelFormatInfo.end()) - return 0; - - unsigned int multiplier = 0; - for (unsigned int i = 0; i < info->numPlanes; ++i) - multiplier += info->planes[i].bitsPerPixel - / info->planes[i].hSubSampling - / info->planes[i].vSubSampling; - - return width * height * multiplier / 8; -} - -PixelFormat V4L2CameraProxy::v4l2ToDrm(uint32_t format) -{ - auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), - [format](const PixelFormatInfo &info) { - return info.v4l2Format == format; - }); - if (info == pixelFormatInfo.end()) - return PixelFormat(); - - return info->format; -} - -uint32_t V4L2CameraProxy::drmToV4L2(const PixelFormat &format) -{ - auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), - [format](const PixelFormatInfo &info) { - return info.format == format; - }); - if (info == pixelFormatInfo.end()) - return format; - - return info->v4l2Format; -} diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index d78a472..e962694 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -40,7 +40,6 @@ private: bool validateBufferType(uint32_t type); bool validateMemoryType(uint32_t memory); void setFmtFromConfig(StreamConfiguration &streamConfig); - unsigned int calculateSizeImage(StreamConfiguration &streamConfig); void querycap(std::shared_ptr camera); void tryFormat(struct v4l2_format *arg); enum v4l2_priority maxPriority(); @@ -69,13 +68,6 @@ private: int acquire(V4L2CameraFile *file); void release(V4L2CameraFile *file); - static unsigned int bplMultiplier(uint32_t format); - static unsigned int imageSize(uint32_t format, unsigned int width, - unsigned int height); - - static PixelFormat v4l2ToDrm(uint32_t format); - static uint32_t drmToV4L2(const PixelFormat &format); - static const std::set supportedIoctls_; unsigned int refcount_; From patchwork Thu Jul 9 13:28:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8737 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 32BBEBD792 for ; Thu, 9 Jul 2020 13:29:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F41476124F; Thu, 9 Jul 2020 15:29:45 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gh7bJtLD"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 78268611B2 for ; Thu, 9 Jul 2020 15:29:44 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 94B6F525; Thu, 9 Jul 2020 15:29:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301384; bh=z9IOjSBpFqm+X0WXiiOGE26Y96dw5D9zVDicpLvH6l8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gh7bJtLDiDRpFDcZXymoIyaeik7auJXrR6Ih1DEmpMKimVbJJWE+ifkVFcnblWkRx W+eWvjohG8kh/W8tv46SNUCbj7p+opDJd9aWaHwltf4Khj9k8CexltHjUEvdOwNwM2 T2FMeMz0NIRlhVo96AA3HRF4cDb+B3tVP+bkY7JM= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:34 +0900 Message-Id: <20200709132835.112593-23-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 22/23] v4l2: v4l2_camera_proxy: Use stream config in tryFormat 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" For handling try_fmt, the values should be filled in by validating the stream configuration, and not by recalculating them or manually checking against the cached list of formats and sizes. Add a new V4L2Camera::validateConfiguration() function to validate a configuration and use it to obtain size, format, stride, and frameSize values. If the format negotiation fails, return error from try_fmt and s_fmt. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v5: - change commit message wording a bit - re-order patches to avoid potential regressions - return error from try_fmt and s_fmt if negotiation fails Changes in v4: - clean up code a bit - squash the implementation and usage New in v3 --- src/v4l2/v4l2_camera.cpp | 20 +++++++++++++++++ src/v4l2/v4l2_camera.h | 3 +++ src/v4l2/v4l2_camera_proxy.cpp | 41 ++++++++++++++++++++-------------- src/v4l2/v4l2_camera_proxy.h | 2 +- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index a923256..61bca07 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -138,6 +138,26 @@ int V4L2Camera::configure(StreamConfiguration *streamConfigOut, return 0; } +int V4L2Camera::validateConfiguration(const PixelFormat &pixelFormat, + const Size &size, + StreamConfiguration *streamConfigOut) +{ + std::unique_ptr config = + camera_->generateConfiguration({ StreamRole::Viewfinder }); + StreamConfiguration &cfg = config->at(0); + cfg.size = size; + cfg.pixelFormat = pixelFormat; + cfg.bufferCount = 1; + + CameraConfiguration::Status validation = config->validate(); + if (validation == CameraConfiguration::Invalid) + return -EINVAL; + + *streamConfigOut = cfg; + + return 0; +} + int V4L2Camera::allocBuffers(unsigned int count) { Stream *stream = config_->at(0).stream(); diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 515e906..be6c4e1 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -47,6 +47,9 @@ public: int configure(StreamConfiguration *streamConfigOut, const Size &size, const PixelFormat &pixelformat, unsigned int bufferCount); + int validateConfiguration(const PixelFormat &pixelformat, + const Size &size, + StreamConfiguration *streamConfigOut); int allocBuffers(unsigned int count); void freeBuffers(); diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 8c55a06..50ab7e6 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -296,33 +296,36 @@ int V4L2CameraProxy::vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg) return 0; } -void V4L2CameraProxy::tryFormat(struct v4l2_format *arg) +int V4L2CameraProxy::tryFormat(struct v4l2_format *arg) { V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat); PixelFormat format = PixelFormatInfo::info(v4l2Format).format; - const std::vector &formats = - streamConfig_.formats().pixelformats(); - if (std::find(formats.begin(), formats.end(), format) == formats.end()) - format = streamConfig_.formats().pixelformats()[0]; - Size size(arg->fmt.pix.width, arg->fmt.pix.height); - const std::vector &sizes = streamConfig_.formats().sizes(format); - if (std::find(sizes.begin(), sizes.end(), size) == sizes.end()) - size = streamConfig_.formats().sizes(format)[0]; - const PixelFormatInfo &formatInfo = PixelFormatInfo::info(format); + StreamConfiguration config; + int ret = vcam_->validateConfiguration(format, size, &config); + if (ret < 0) { + LOG(V4L2Compat, Error) + << "Failed to negotiate a valid format: " + << format.toString(); + return -EINVAL; + } + + const PixelFormatInfo &info = PixelFormatInfo::info(config.pixelFormat); - arg->fmt.pix.width = size.width; - arg->fmt.pix.height = size.height; - arg->fmt.pix.pixelformat = formatInfo.v4l2Format; + arg->fmt.pix.width = config.size.width; + arg->fmt.pix.height = config.size.height; + arg->fmt.pix.pixelformat = info.v4l2Format; arg->fmt.pix.field = V4L2_FIELD_NONE; - arg->fmt.pix.bytesperline = formatInfo.stride(size.width, 0); - arg->fmt.pix.sizeimage = formatInfo.frameSize(size); + arg->fmt.pix.bytesperline = config.stride; + arg->fmt.pix.sizeimage = config.frameSize; arg->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; arg->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; arg->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; arg->fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; arg->fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; + + return 0; } int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) @@ -339,7 +342,9 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg) if (ret < 0) return ret; - tryFormat(arg); + ret = tryFormat(arg); + if (ret < 0) + return ret; Size size(arg->fmt.pix.width, arg->fmt.pix.height); V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat); @@ -361,7 +366,9 @@ int V4L2CameraProxy::vidioc_try_fmt(V4L2CameraFile *file, struct v4l2_format *ar if (!validateBufferType(arg->type)) return -EINVAL; - tryFormat(arg); + int ret = tryFormat(arg); + if (ret < 0) + return ret; return 0; } diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index e962694..f06b5b8 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -41,7 +41,7 @@ private: bool validateMemoryType(uint32_t memory); void setFmtFromConfig(StreamConfiguration &streamConfig); void querycap(std::shared_ptr camera); - void tryFormat(struct v4l2_format *arg); + int tryFormat(struct v4l2_format *arg); enum v4l2_priority maxPriority(); void updateBuffers(); void freeBuffers(); From patchwork Thu Jul 9 13:28:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8738 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 83816BD792 for ; Thu, 9 Jul 2020 13:29:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 51121611BA; Thu, 9 Jul 2020 15:29:48 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qVeLRk4l"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C163E611B2 for ; Thu, 9 Jul 2020 15:29:46 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EB49E525; Thu, 9 Jul 2020 15:29:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1594301386; bh=snaqUun6n9obVuM8zCpQZ8/093P7lRU+gTulHWcuI/8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qVeLRk4lVqnYuV1ycvCVXUsPumnw+fDk795OjRTeswd/h9cDyK0V7rSmSQLScqMCG aYFoHzvcdKUoOHw64prleQscXi6lmjeAuCKUhpMzZQACvyl/WlxypvZaxGhvdtzXK7 CKdJ6E5CfukhhnYqsbJ7VrqZkFfuygU95Vp3P0O8= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Jul 2020 22:28:35 +0900 Message-Id: <20200709132835.112593-24-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200709132835.112593-1-paul.elder@ideasonboard.com> References: <20200709132835.112593-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 23/23] tests: v4l2_compat: Add test for v4l2_compat 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Test the V4L2 compatibility layer by running v4l2-compliance -s on every /dev/video* device. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v5 - add raspi to supported pipelines Changes in v4: - fail the test if v4l2-ctl fails (for example, if libcamera dies fatally) Changes in v3: - use argparse - add argument to test all cameras, and test only one camera per driver by default - print the devices that we're testing and if each succeeded or failed Changes in v2: - change all strings to single-quote - simplify meson.build - get path to v4l2-compat.so from cli arg, rather than running custom find() - remove find_file() - extend test timeout to 60 seconds (from default of 30) - don't run v4l2-compliance subprocesses in shell - check if v4l2-compliance runs are killed by signal (eg. the known SIGABRT due to floating point exception) - move the check to see if libcamera supports the camera to v4l2-ctl instead of v4l2-compliance (in v1 we only checked if the pipeline was supported with v4l2-ctl) --- test/meson.build | 1 + test/v4l2_compat/meson.build | 10 ++ test/v4l2_compat/v4l2_compat_test.py | 152 +++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 test/v4l2_compat/meson.build create mode 100755 test/v4l2_compat/v4l2_compat_test.py diff --git a/test/meson.build b/test/meson.build index 7808a26..f41d6e7 100644 --- a/test/meson.build +++ b/test/meson.build @@ -12,6 +12,7 @@ subdir('pipeline') subdir('process') subdir('serialization') subdir('stream') +subdir('v4l2_compat') subdir('v4l2_subdevice') subdir('v4l2_videodevice') diff --git a/test/v4l2_compat/meson.build b/test/v4l2_compat/meson.build new file mode 100644 index 0000000..5b29de7 --- /dev/null +++ b/test/v4l2_compat/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: CC0-1.0 + +if is_variable('v4l2_compat') + v4l2_compat_test = files('v4l2_compat_test.py') + + test('v4l2_compat_test', v4l2_compat_test, + args : v4l2_compat, + suite : 'v4l2_compat', + timeout : 60) +endif diff --git a/test/v4l2_compat/v4l2_compat_test.py b/test/v4l2_compat/v4l2_compat_test.py new file mode 100755 index 0000000..99b3d5a --- /dev/null +++ b/test/v4l2_compat/v4l2_compat_test.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020, Google Inc. +# +# Author: Paul Elder +# +# v4l2_compat_test.py - Test the V4L2 compatibility layer + +import argparse +import glob +import os +import re +import shutil +import signal +import subprocess +import sys + +TestPass = 0 +TestFail = -1 +TestSkip = 77 + + +supported_pipelines = [ + 'bcm2835-isp', + 'uvcvideo', + 'vimc', +] + + +def grep(exp, arr): + return [s for s in arr if re.search(exp, s)] + + +def run_with_stdout(*args, env={}): + try: + with open(os.devnull, 'w') as devnull: + output = subprocess.check_output(args, env=env, stderr=devnull) + ret = 0 + except subprocess.CalledProcessError as err: + output = err.output + ret = err.returncode + return ret, output.decode('utf-8').split('\n') + + +def extract_result(result): + res = result.split(', ') + ret = {} + ret['total'] = int(res[0].split(': ')[-1]) + ret['succeeded'] = int(res[1].split(': ')[-1]) + ret['failed'] = int(res[2].split(': ')[-1]) + ret['warnings'] = int(res[3].split(': ')[-1]) + ret['device'] = res[0].split()[4].strip(':') + ret['driver'] = res[0].split()[2] + return ret + + +def print_output_arr(output_arr): + print('\n'.join(output_arr)) + + +def test_v4l2_compliance(v4l2_compliance, v4l2_compat, device, base_driver): + ret, output = run_with_stdout(v4l2_compliance, '-s', '-d', device, env={'LD_PRELOAD': v4l2_compat}) + if ret < 0: + print_output_arr(output) + print(f'Test for {device} terminated due to signal {signal.Signals(-ret).name}') + return TestFail + + result = extract_result(output[-2]) + if result['failed'] == 0: + return TestPass + + # vimc will fail s_fmt because it only supports framesizes that are + # multiples of 3 + if base_driver == 'vimc' and result['failed'] == 1: + failures = grep('fail', output) + if re.search('S_FMT cannot handle an invalid format', failures[0]) is None: + print_output_arr(output) + return TestFail + return TestPass + + print_output_arr(output) + return TestFail + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument('-a', '--all', action='store_true', + help='Test all available cameras') + parser.add_argument('v4l2_compat', type=str, + help='Path to v4l2-compat.so') + args = parser.parse_args(argv[1:]) + + v4l2_compat = args.v4l2_compat + + v4l2_compliance = shutil.which('v4l2-compliance') + if v4l2_compliance is None: + print('v4l2-compliance is not available') + return TestSkip + + v4l2_ctl = shutil.which('v4l2-ctl') + if v4l2_ctl is None: + print('v4l2-ctl is not available') + return TestSkip + + dev_nodes = glob.glob('/dev/video*') + if len(dev_nodes) == 0: + print('no video nodes available to test with') + return TestSkip + + failed = [] + drivers_tested = {} + for device in dev_nodes: + ret, out = run_with_stdout(v4l2_ctl, '-D', '-d', device, env={'LD_PRELOAD': v4l2_compat}) + if ret < 0: + failed.append(device) + print(f'v4l2-ctl failed on {device} with v4l2-compat') + continue + driver = grep('Driver name', out)[0].split(':')[-1].strip() + if driver != "libcamera": + continue + + ret, out = run_with_stdout(v4l2_ctl, '-D', '-d', device) + if ret < 0: + failed.append(device) + print(f'v4l2-ctl failed on {device} without v4l2-compat') + continue + driver = grep('Driver name', out)[0].split(':')[-1].strip() + if driver not in supported_pipelines: + continue + + if not args.all and driver in drivers_tested: + continue + + print(f'Testing {device} with {driver} driver... ', end='') + ret = test_v4l2_compliance(v4l2_compliance, v4l2_compat, device, driver) + if ret == TestFail: + failed.append(device) + print('failed') + else: + print('success') + drivers_tested[driver] = True + + if len(failed) > 0: + print(f'Failed {len(failed)} tests:') + for device in failed: + print(f'- {device}') + + return TestPass if not failed else TestFail + + +if __name__ == '__main__': + sys.exit(main(sys.argv))