From patchwork Tue Jun 30 14:58:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8520 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 309E2BF415 for ; Tue, 30 Jun 2020 14:58:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F20EF60C5D; Tue, 30 Jun 2020 16:58: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="Oql/RiQh"; 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 7D5D1609C5 for ; Tue, 30 Jun 2020 16:58:25 +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 A5DC929F; Tue, 30 Jun 2020 16:58:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593529105; bh=3pho5HysZIyjdNq9D73yib8QFeMOhaYLjUPQFC/mcZ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Oql/RiQhyxtwkHTfFn7qiCV9z773HrTXRh9RACxvoXrTD+N83rXqd37Q6cletUZ3o feuC/yjjWBFOnBzykuvjt19rDXA4FL7w593nj3aBk4d1o1ZvWhdslLoI40Lndpp5gF oWOWKZl6/Bv+GSakGpigMLRowyZz25ST9Bjs8YIk= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 23:58:03 +0900 Message-Id: <20200630145808.2976956-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200630145808.2976956-1-paul.elder@ideasonboard.com> References: <20200630145808.2976956-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/6] 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 --- No change in v2 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 Tue Jun 30 14:58:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8521 X-Patchwork-Delegate: paul.elder@ideasonboard.com 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 97EA5BF415 for ; Tue, 30 Jun 2020 14:58:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 63C3060C5D; Tue, 30 Jun 2020 16:58: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="G4s9cIKB"; 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 4E215609C5 for ; Tue, 30 Jun 2020 16:58:27 +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 CA84629F; Tue, 30 Jun 2020 16:58:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593529107; bh=EpVFsCs5asu3rKfqYsgmtgQU6x9Dji3d9jsxyxxfkuc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G4s9cIKBwv1qL6Ud9NMPvvvBKHK2T7lJxXV64fr8As92g69FEDjAO5f2m4OXkQ/ru dpK9Xa0rI8g67yu+BNCjfMgc2NjFxkpTqhiktY9HvJvnL3iGAvxWe0qnm5YsQvcRQV yp37JucLbQvZbXMohwU1kFP8NtdLvF/IhOJcp3vs= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 23:58:04 +0900 Message-Id: <20200630145808.2976956-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200630145808.2976956-1-paul.elder@ideasonboard.com> References: <20200630145808.2976956-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/6] libcamera: formats: Add fields to info 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. For example, for something simple like BGR888, it is self-explanatory: the pixel group size is 1, and the bytes necessary is 3. 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). NV12 seems like it shold be 6 bytes with 4 pixels, since there is downsampling in the Y axis as well, however, the pixel group is only in terms of rows, so it is half of that, at 2 pixels and 3 bytes. The IPU3 formats are also self-explanatory, coming from a comment in the driver, a pixel group is 50, and it consumes 64 bytes. Signed-off-by: Paul Elder --- 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 | 4 +- src/libcamera/formats.cpp | 111 ++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index f59ac8f..dc19492 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -45,13 +45,15 @@ public: static const PixelFormatInfo &info(const PixelFormat &format); - /* \todo Add support for non-contiguous memory planes */ const char *name; PixelFormat format; V4L2PixelFormat v4l2Format; unsigned int bitsPerPixel; enum ColourEncoding colourEncoding; bool packed; + + unsigned int bytesPerGroup; + unsigned int pixelsPerGroup; }; } /* namespace libcamera */ diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index d3b722c..8076c39 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -152,6 +152,26 @@ 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::bytesPerGroup + * \brief The number of bytes that a pixel group consumes + * + * \sa pixelsPerGroup + * + * \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. 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, and include bytes that are used in all planes (for + * multiplanar formats). */ /** @@ -179,6 +199,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::RGB888, { .name = "RGB888", @@ -187,6 +209,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::ABGR8888, { .name = "ABGR8888", @@ -195,6 +219,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, { formats::ARGB8888, { .name = "ARGB8888", @@ -203,6 +229,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, { formats::BGRA8888, { .name = "BGRA8888", @@ -211,6 +239,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, { formats::RGBA8888, { .name = "RGBA8888", @@ -219,6 +249,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, /* YUV packed formats. */ @@ -229,6 +261,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::YVYU, { .name = "YVYU", @@ -237,6 +271,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::UYVY, { .name = "UYVY", @@ -245,6 +281,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::VYUY, { .name = "VYUY", @@ -253,6 +291,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, /* YUV planar formats. */ @@ -263,6 +303,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::NV21, { .name = "NV21", @@ -271,6 +313,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::NV16, { .name = "NV16", @@ -279,6 +323,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::NV61, { .name = "NV61", @@ -287,6 +333,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::NV24, { .name = "NV24", @@ -295,6 +343,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::NV42, { .name = "NV42", @@ -303,6 +353,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::YUV420, { .name = "YUV420", @@ -311,6 +363,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::YUV422, { .name = "YUV422", @@ -319,6 +373,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, /* Greyscale formats. */ @@ -329,6 +385,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 1, + .pixelsPerGroup = 1, } }, /* Bayer formats. */ @@ -339,6 +397,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SGBRG8, { .name = "SGBRG8", @@ -347,6 +407,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SGRBG8, { .name = "SGRBG8", @@ -355,6 +417,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SRGGB8, { .name = "SRGGB8", @@ -363,6 +427,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SBGGR10, { .name = "SBGGR10", @@ -371,6 +437,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGBRG10, { .name = "SGBRG10", @@ -379,6 +447,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGRBG10, { .name = "SGRBG10", @@ -387,6 +457,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SRGGB10, { .name = "SRGGB10", @@ -395,6 +467,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SBGGR10_CSI2P, { .name = "SBGGR10_CSI2P", @@ -403,6 +477,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SGBRG10_CSI2P, { .name = "SGBRG10_CSI2P", @@ -411,6 +487,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SGRBG10_CSI2P, { .name = "SGRBG10_CSI2P", @@ -419,6 +497,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SRGGB10_CSI2P, { .name = "SRGGB10_CSI2P", @@ -427,6 +507,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SBGGR12, { .name = "SBGGR12", @@ -435,6 +517,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGBRG12, { .name = "SGBRG12", @@ -443,6 +527,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGRBG12, { .name = "SGRBG12", @@ -451,6 +537,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SRGGB12, { .name = "SRGGB12", @@ -459,6 +547,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SBGGR12_CSI2P, { .name = "SBGGR12_CSI2P", @@ -467,6 +557,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SGBRG12_CSI2P, { .name = "SGBRG12_CSI2P", @@ -475,6 +567,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SGRBG12_CSI2P, { .name = "SGRBG12_CSI2P", @@ -483,6 +577,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SRGGB12_CSI2P, { .name = "SRGGB12_CSI2P", @@ -491,6 +587,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SBGGR10_IPU3, { .name = "SBGGR10_IPU3", @@ -499,6 +597,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, { formats::SGBRG10_IPU3, { .name = "SGBRG10_IPU3", @@ -507,6 +607,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, { formats::SGRBG10_IPU3, { .name = "SGRBG10_IPU3", @@ -515,6 +617,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, { formats::SRGGB10_IPU3, { .name = "SRGGB10_IPU3", @@ -523,16 +627,21 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, /* Compressed formats. */ + /* \todo Allow pipeline handlers to fill in parameters of formats. */ { formats::MJPEG, { .name = "MJPEG", .format = formats::MJPEG, .v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_MJPEG), - .bitsPerPixel = 0, + .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, }; From patchwork Tue Jun 30 14:58:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8522 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 1B8BBBF415 for ; Tue, 30 Jun 2020 14:58:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DD38260C5C; Tue, 30 Jun 2020 16:58:30 +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="FbTsWXWa"; 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 4725A60C56 for ; Tue, 30 Jun 2020 16:58: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 A546A29F; Tue, 30 Jun 2020 16:58:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593529109; bh=mDfv4gVQq4n7zh6dVF0MMtT5tfS6pZG/kWQ0ES64DEI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FbTsWXWaLRDbRCaE0OETdInreEPSPjyRxV20/GzIjFEijMO7fj2DfWOqPbP9N24Xs mQbHW8uOtetZH4P15edVdR4LsO60ttBebevvNSmPgOpR7gHJc1L3nLElAcD/bnJYCd j2Z0yZn34jv4vZ6Uxsd6YAUjnoI3BY06l7PCRR7c= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 23:58:05 +0900 Message-Id: <20200630145808.2976956-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200630145808.2976956-1-paul.elder@ideasonboard.com> References: <20200630145808.2976956-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/6] 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 --- Changes in v2: - move invalid PixelFormatInfo instance to anonymous namespace - add documentation --- include/libcamera/internal/formats.h | 1 + src/libcamera/formats.cpp | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index dc19492..3c7440a 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -44,6 +44,7 @@ public: bool isValid() const { return format.isValid(); } static const PixelFormatInfo &info(const PixelFormat &format); + static const PixelFormatInfo &info(const V4L2PixelFormat &format); const char *name; PixelFormat format; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index 8076c39..4d18825 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -7,6 +7,7 @@ #include "libcamera/internal/formats.h" +#include #include #include @@ -190,6 +191,8 @@ const std::map> &ImageFormats::data() const namespace { +const PixelFormatInfo invalid{}; + const std::map pixelFormatInfo{ /* RGB formats. */ { formats::BGR888, { @@ -661,8 +664,6 @@ 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) @@ -674,4 +675,22 @@ const PixelFormatInfo &PixelFormatInfo::info(const PixelFormat &format) 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) +{ + auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(), + [format](auto pair) { + return pair.second.v4l2Format == format; + }); + if (info == pixelFormatInfo.end()) + return invalid; + + return info->second; +} + } /* namespace libcamera */ From patchwork Tue Jun 30 14:58:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8523 X-Patchwork-Delegate: paul.elder@ideasonboard.com 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 7B5CEBF415 for ; Tue, 30 Jun 2020 14:58:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 480BD60C61; Tue, 30 Jun 2020 16:58:32 +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="CQwDS5DF"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 19EAD60C5F for ; Tue, 30 Jun 2020 16:58:31 +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 970A329F; Tue, 30 Jun 2020 16:58:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593529110; bh=Gy7Ju+OuZwBHQkoZozUhku4niNFTxzhbSrTNSWuo3Gs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CQwDS5DFWEPTbrqrEHKDiuxhv3I4PV7KkrHDI3EfHUAvZAbaVW+Z0bHEOfsH50pCq 3350+sOLLXxa3WWnAEjjM1/zKV/j4LeyNDura0+LZ3fMtQyaOMYtj4ZUfMgLzYWVVV 1Ha1mu2iVMUa4dDGowtFcyhNAL8EFgz2AplfFE78= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 23:58:06 +0900 Message-Id: <20200630145808.2976956-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200630145808.2976956-1-paul.elder@ideasonboard.com> References: <20200630145808.2976956-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/6] libcamera: PixelFormatInfo: Add functions bytesPerLine and imageSize 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 bytes-per-line and image size. This will simplify existing code that calculates these things. Signed-off-by: Paul Elder --- Changes in v2: - make these functions const - add documentation - inline DIV_ROUND_UP --- include/libcamera/internal/formats.h | 3 +++ src/libcamera/formats.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index 3c7440a..af0f1ac 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -46,6 +46,9 @@ public: static const PixelFormatInfo &info(const PixelFormat &format); static const PixelFormatInfo &info(const V4L2PixelFormat &format); + unsigned int bytesPerLine(unsigned int width) const; + unsigned int imageSize(const Size &size) const; + const char *name; PixelFormat format; V4L2PixelFormat v4l2Format; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index 4d18825..698c905 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -693,4 +693,31 @@ const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format) return info->second; } +/** + * \brief Compute the bytes per line + * \param[in] width The width of the line, in pixels + * \return The number of bytes necessary to store the line, or 0 if the + * PixelFormatInfo instance not valid + */ +unsigned int PixelFormatInfo::bytesPerLine(unsigned int width) const +{ + if (!isValid()) + return 0; + + /* ceil(width / pixelsPerGroup) * bytesPerGroup */ + return ((width + pixelsPerGroup - 1) / pixelsPerGroup) * bytesPerGroup; + +} + +/** + * \brief Compute the bytes necessary to store the frame + * \param[in] size The size of the frame, in pixels + * \return The number of bytes necessary to store the frame, or 0 if the + * PixelFormatInfo instance is not valid + */ +unsigned int PixelFormatInfo::imageSize(const Size &size) const +{ + return size.height * bytesPerLine(size.width); +} + } /* namespace libcamera */ From patchwork Tue Jun 30 14:58:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8524 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 CF36BBF415 for ; Tue, 30 Jun 2020 14:58:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 99EE060C60; Tue, 30 Jun 2020 16:58: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="XWV46s2f"; 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 334A960C55 for ; Tue, 30 Jun 2020 16:58:33 +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 70B5829F; Tue, 30 Jun 2020 16:58:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593529113; bh=dg5QwoN437Ij7WTk5xjQ+AYAq638k9q1jSWYqj4UC+0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XWV46s2f9VGUdMtFwCUVcU6TAX/wtevzvkeJh3WtzMs+wsTcj5CZB+5xKT7e0S03D GqLsb57O3a3QBCYxLt3nFBYCZQ6EynMY6y767d9yCdlsHIvEbXsDSI1PYYudlCQGRO 0dPmpdqAb30RX6ihIVXLnmns02LKTKR21cLxqb4o= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 23:58:07 +0900 Message-Id: <20200630145808.2976956-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200630145808.2976956-1-paul.elder@ideasonboard.com> References: <20200630145808.2976956-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/6] 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 --- 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 9d887b7..4d9ec9c 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 Tue Jun 30 14:58:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8525 X-Patchwork-Delegate: paul.elder@ideasonboard.com 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 400E4BF415 for ; Tue, 30 Jun 2020 14:58:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 031D960C61; Tue, 30 Jun 2020 16:58: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="Tmt9XZOm"; 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 1661E60C55 for ; Tue, 30 Jun 2020 16:58:35 +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 957F229F; Tue, 30 Jun 2020 16:58:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593529114; bh=GSApLTZ4SFGGVUjnvBwiD43yd/nGOtsclaS7rd8yLQg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Tmt9XZOmeAcspuYuW9fav2RuXigYEvwYDwJfmRI6scb75LvP1hkO4qm77TXUuAJ0I Mtzzsf4APukqx2LB8dX0OdXQ6B+/4yWbcy/1WPTEbwckAwwluRRSF+gUaMMFARiY62 RJttbfUFbu1yhLvBzm5JQzALrGRSoBwmMXlrresg= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 23:58:08 +0900 Message-Id: <20200630145808.2976956-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200630145808.2976956-1-paul.elder@ideasonboard.com> References: <20200630145808.2976956-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 6/6] v4l2: v4l2_camera_proxy: Use libcamera 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" Now that calculation of bytes per line, image size, and conversions to and from v4l2 and drm formats have been moved into libcamera core, removed them from V4L2CameraProxy. This has a positive side-effect of cleaning up the code. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v2: - clean up the code a bit more --- src/v4l2/v4l2_camera_proxy.cpp | 165 +++++++-------------------------- src/v4l2/v4l2_camera_proxy.h | 7 -- 2 files changed, 34 insertions(+), 138 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index c246570..485e4b6 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" @@ -164,22 +165,20 @@ 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 = info.bytesPerLine(size.width); + curV4L2Format_.fmt.pix.sizeimage = info.imageSize(size); + 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) @@ -188,9 +187,9 @@ unsigned int V4L2CameraProxy::calculateSizeImage(StreamConfiguration &streamConf * \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); + const PixelFormatInfo &info = PixelFormatInfo::info(streamConfig.pixelFormat); + + return info.imageSize(streamConfig.size); } void V4L2CameraProxy::querycap(std::shared_ptr camera) @@ -253,12 +252,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 +279,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 +308,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 +320,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.bytesPerLine(size.width); + arg->fmt.pix.sizeimage = formatInfo.imageSize(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,8 +352,9 @@ 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; @@ -495,8 +498,9 @@ 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; @@ -835,104 +839,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..49184a1 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -69,13 +69,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_;