From patchwork Mon Jun 29 15:14: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: 8500 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 4B62ABFFE2 for ; Mon, 29 Jun 2020 15:14:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 103D6609DF; Mon, 29 Jun 2020 17:14:26 +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="Yyh7FBdT"; 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 A737D603B4 for ; Mon, 29 Jun 2020 17:14: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 3F800299; Mon, 29 Jun 2020 17:14:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593443664; bh=hakLbbDlnyNZGsnHzZIbnjRyPI+c1jtPXJjxk2lb5ds=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Yyh7FBdTCOeMeoN/Kpt+UwVONYV8J32Y1qIWQaTMFX0VbcykPTZ7wNXL/1HhmA3Y9 1YPy+I9Tsy8G+bwn5bG1Q5ayaaa3EIY6u8rznJTBBMRMOjK0NCVoDDlQH8rs0l+LUi 5gp0Jq8IG/awPNxGEDEhQkAZlGkdxe/WkJGRBzYA= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 00:14:06 +0900 Message-Id: <20200629151411.216477-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200629151411.216477-1-paul.elder@ideasonboard.com> References: <20200629151411.216477-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 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 --- 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 Mon Jun 29 15:14: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: 8501 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 AF132BFFE2 for ; Mon, 29 Jun 2020 15:14:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7DC1160AF4; Mon, 29 Jun 2020 17:14: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="lesCgr0B"; 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 8F32660A16 for ; Mon, 29 Jun 2020 17:14: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 03956299; Mon, 29 Jun 2020 17:14:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593443666; bh=97LMbeOoKeJHa0/whTGy5AHoSYrzXFKR3B8EuIYWo/w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lesCgr0BYV9H7NeapyQXgu2LwsUcVC1q0nySmrgaDjAfk8mNXabx5HTVIDOVG62QA 4j4kwHFpPzyUGQZ5lrbI3JwjQmkKpH5WQXjG4vKGcGoTbYY+FxWqzDHO4QgXsfrTub XrwAux1DJu6mr9qm320LQUXRmI66ieokPkaX7L4E= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 00:14:07 +0900 Message-Id: <20200629151411.216477-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200629151411.216477-1-paul.elder@ideasonboard.com> References: <20200629151411.216477-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/6] libcamera: formats: Add fields to info ease calculating bpl 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 bytes-per-line as well as buffer 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 bytes-per-line and bytesused. 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 --- include/libcamera/internal/formats.h | 4 +- src/libcamera/formats.cpp | 95 +++++++++++++++++++++++++++- 2 files changed, 97 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..88b5168 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -179,6 +179,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::RGB888, { .name = "RGB888", @@ -187,6 +189,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::ABGR8888, { .name = "ABGR8888", @@ -195,6 +199,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, { formats::ARGB8888, { .name = "ARGB8888", @@ -203,6 +209,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, { formats::BGRA8888, { .name = "BGRA8888", @@ -211,6 +219,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, { formats::RGBA8888, { .name = "RGBA8888", @@ -219,6 +229,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 32, .colourEncoding = PixelFormatInfo::ColourEncodingRGB, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 1, } }, /* YUV packed formats. */ @@ -229,6 +241,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::YVYU, { .name = "YVYU", @@ -237,6 +251,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::UYVY, { .name = "UYVY", @@ -245,6 +261,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::VYUY, { .name = "VYUY", @@ -253,6 +271,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, /* YUV planar formats. */ @@ -263,6 +283,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::NV21, { .name = "NV21", @@ -271,6 +293,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::NV16, { .name = "NV16", @@ -279,6 +303,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::NV61, { .name = "NV61", @@ -287,6 +313,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::NV24, { .name = "NV24", @@ -295,6 +323,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::NV42, { .name = "NV42", @@ -303,6 +333,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 24, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 1, } }, { formats::YUV420, { .name = "YUV420", @@ -311,6 +343,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::YUV422, { .name = "YUV422", @@ -319,6 +353,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 16, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, /* Greyscale formats. */ @@ -329,6 +365,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingYUV, .packed = false, + .bytesPerGroup = 1, + .pixelsPerGroup = 1, } }, /* Bayer formats. */ @@ -339,6 +377,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SGBRG8, { .name = "SGBRG8", @@ -347,6 +387,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SGRBG8, { .name = "SGRBG8", @@ -355,6 +397,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SRGGB8, { .name = "SRGGB8", @@ -363,6 +407,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 8, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 2, + .pixelsPerGroup = 2, } }, { formats::SBGGR10, { .name = "SBGGR10", @@ -371,6 +417,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGBRG10, { .name = "SGBRG10", @@ -379,6 +427,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGRBG10, { .name = "SGRBG10", @@ -387,6 +437,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SRGGB10, { .name = "SRGGB10", @@ -395,6 +447,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SBGGR10_CSI2P, { .name = "SBGGR10_CSI2P", @@ -403,6 +457,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SGBRG10_CSI2P, { .name = "SGBRG10_CSI2P", @@ -411,6 +467,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SGRBG10_CSI2P, { .name = "SGRBG10_CSI2P", @@ -419,6 +477,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SRGGB10_CSI2P, { .name = "SRGGB10_CSI2P", @@ -427,6 +487,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 5, + .pixelsPerGroup = 4, } }, { formats::SBGGR12, { .name = "SBGGR12", @@ -435,6 +497,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGBRG12, { .name = "SGBRG12", @@ -443,6 +507,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SGRBG12, { .name = "SGRBG12", @@ -451,6 +517,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SRGGB12, { .name = "SRGGB12", @@ -459,6 +527,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = false, + .bytesPerGroup = 4, + .pixelsPerGroup = 2, } }, { formats::SBGGR12_CSI2P, { .name = "SBGGR12_CSI2P", @@ -467,6 +537,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SGBRG12_CSI2P, { .name = "SGBRG12_CSI2P", @@ -475,6 +547,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SGRBG12_CSI2P, { .name = "SGRBG12_CSI2P", @@ -483,6 +557,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SRGGB12_CSI2P, { .name = "SRGGB12_CSI2P", @@ -491,6 +567,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 12, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 3, + .pixelsPerGroup = 2, } }, { formats::SBGGR10_IPU3, { .name = "SBGGR10_IPU3", @@ -499,6 +577,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, { formats::SGBRG10_IPU3, { .name = "SGBRG10_IPU3", @@ -507,6 +587,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, { formats::SGRBG10_IPU3, { .name = "SGRBG10_IPU3", @@ -515,6 +597,8 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, { formats::SRGGB10_IPU3, { .name = "SRGGB10_IPU3", @@ -523,16 +607,25 @@ const std::map pixelFormatInfo{ .bitsPerPixel = 10, .colourEncoding = PixelFormatInfo::ColourEncodingRAW, .packed = true, + .bytesPerGroup = 64, + .pixelsPerGroup = 50, } }, /* 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, { .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 Mon Jun 29 15:14: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: 8502 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 22428BFFE2 for ; Mon, 29 Jun 2020 15:14:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E3E8A60AF6; Mon, 29 Jun 2020 17:14: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="cDkY9qGr"; 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 5EB66609C2 for ; Mon, 29 Jun 2020 17:14:28 +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 E664A299; Mon, 29 Jun 2020 17:14:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593443668; bh=lvaWxNC2vBsXG/kCDkB+qXNaNGTuoiq6AmY/yu/RqsY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cDkY9qGrg6qb2DNZRxaMkkgdM6C8oqJLRuCFzPWQOradiAzmWdA8TrNLXPLmyg7lT sh3PE+KKpY00+umqH3vVEdBCYDLKL6xlurbdmcXINjbcDs6BPlin1Ut5kg6+v+EYhC Qkkg8zV9zqaH+5VhUwG5YSQEgL9eop+2Bbt2ued4= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 00:14:08 +0900 Message-Id: <20200629151411.216477-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200629151411.216477-1-paul.elder@ideasonboard.com> References: <20200629151411.216477-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/6] libcamera: formats: PixelFormatInfo: Add v4l2 constructor 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 constructor for PixelFormatInfo that takes a V4L2PixelFormat. Signed-off-by: Paul Elder --- include/libcamera/internal/formats.h | 1 + src/libcamera/formats.cpp | 16 ++++++++++++++-- 2 files changed, 15 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 88b5168..7029a94 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -631,6 +631,8 @@ const std::map pixelFormatInfo{ } /* namespace */ +static const PixelFormatInfo invalid{}; + /** * \fn bool PixelFormatInfo::isValid() const * \brief Check if the pixel format info is valid @@ -645,8 +647,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) @@ -658,4 +658,16 @@ const PixelFormatInfo &PixelFormatInfo::info(const PixelFormat &format) return iter->second; } +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 Mon Jun 29 15:14:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8503 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 87046BFFE2 for ; Mon, 29 Jun 2020 15:14:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 431F060AF9; Mon, 29 Jun 2020 17:14:31 +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="wUr0DQP4"; 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 2A93A609C8 for ; Mon, 29 Jun 2020 17:14:30 +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 BA45D299; Mon, 29 Jun 2020 17:14:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593443669; bh=uDGAMhzcGy4/p/LxfmWvTyzPftJuB8tIFbXFSA0nhjI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wUr0DQP4oW5a2XRK8m53YhZ/Sp2tdx4Agqdlj7FnuWdrbyxVglu85jrwKubgk8CSO Uo/UYr7ybP293o1Z3BZsSwXJFi6Zn4qcBnpwalmq3Eg2UkTo3itnMUu7r22X8gKbi0 IExVXQkZLocsWo/AC+vB/oBRohSmGhpw6A9df4wU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 00:14:09 +0900 Message-Id: <20200629151411.216477-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200629151411.216477-1-paul.elder@ideasonboard.com> References: <20200629151411.216477-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/6] libcamera: PixelFormatInfo: Add methods 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 instance methods to PixelFormatInfo for calculating bytes-per-line and image size. This will simplify existing code that calculates these things. Signed-off-by: Paul Elder --- include/libcamera/internal/formats.h | 3 +++ src/libcamera/formats.cpp | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index 3c7440a..1372a43 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); + unsigned int imageSize(unsigned int width, unsigned int height); + const char *name; PixelFormat format; V4L2PixelFormat v4l2Format; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index 7029a94..dc1d348 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -7,12 +7,16 @@ #include "libcamera/internal/formats.h" +#include #include #include #include "libcamera/internal/log.h" + +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + /** * \file internal/formats.h * \brief Types and helper methods to handle libcamera image formats @@ -670,4 +674,21 @@ const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format) return info->second; } +unsigned int PixelFormatInfo::bytesPerLine(unsigned int width) +{ + if (!isValid()) + return 0; + + return DIV_ROUND_UP(width, pixelsPerGroup) * bytesPerGroup; + +} + +unsigned int PixelFormatInfo::imageSize(unsigned int width, unsigned int height) +{ + if (!isValid()) + return 0; + + return height * bytesPerLine(width); +} + } /* namespace libcamera */ From patchwork Mon Jun 29 15:14:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8504 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 BAAA9BFFE2 for ; Mon, 29 Jun 2020 15:14:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8748C609DB; Mon, 29 Jun 2020 17:14: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="vS0XOvrz"; 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 D11CC609D6 for ; Mon, 29 Jun 2020 17:14: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 82FAF299; Mon, 29 Jun 2020 17:14:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593443671; bh=ucl81Rt0CNYtuuGXD8xAI/9X0uErQmRcE/YwOq6BcGA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vS0XOvrzP9GEC0v0sKQspOj4e8npqGaKXFfh86WDgse1Z3KuBlQkWz9EjsvNXadEe T97oGBj/NkyE48TTy0Ym2N9br6aGFk1EhXhj4kptXi1epUiDobs+TWyzud06yxL29f 2xFA4t9baGyXWcBeRbWNZ6zuyu1uYv788wc+pQZ4= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 00:14:10 +0900 Message-Id: <20200629151411.216477-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200629151411.216477-1-paul.elder@ideasonboard.com> References: <20200629151411.216477-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 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 fetching PixelFormatInfo using a V4L2 format by using the new PixelFormatInfo constructor based on V4L2 format. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- 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 Mon Jun 29 15:14:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8505 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 1D49CBFFE2 for ; Mon, 29 Jun 2020 15:14:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D1C7E609DB; Mon, 29 Jun 2020 17:14: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="byHQX/5X"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1C49F603B4 for ; Mon, 29 Jun 2020 17:14: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 414E3299; Mon, 29 Jun 2020 17:14:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593443673; bh=a1kQ2Qhnudlq7IfVoZ7DTM0MgafcnQ8k5bpI83qIHmo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=byHQX/5XSwGFcgYyskuCUK1Ao2dydC6PO4TH8UD8Wc7t+P9yMcrnpjhRoHaCR6Qz4 fEjQPpKZwRvhDT0pDdJR2DwDV2NzexZ0KTa8lCmADPfaYDRGSkmjHV3K/MlZY4kst+ 4fB9C4DNT71V5KAb/8fwkBSxu5myqGzt7nQkMWLM= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Jun 2020 00:14:11 +0900 Message-Id: <20200629151411.216477-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200629151411.216477-1-paul.elder@ideasonboard.com> References: <20200629151411.216477-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 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 --- src/v4l2/v4l2_camera_proxy.cpp | 167 +++++++-------------------------- src/v4l2/v4l2_camera_proxy.h | 7 -- 2 files changed, 36 insertions(+), 138 deletions(-) diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index c246570..0869797 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,21 @@ 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; + PixelFormatInfo formatInfo = PixelFormatInfo::info(streamConfig.pixelFormat); + unsigned int width = streamConfig.size.width; + unsigned int height = streamConfig.size.height; + + curV4L2Format_.fmt.pix.width = width; + curV4L2Format_.fmt.pix.height = height; + curV4L2Format_.fmt.pix.pixelformat = formatInfo.v4l2Format; + curV4L2Format_.fmt.pix.field = V4L2_FIELD_NONE; + curV4L2Format_.fmt.pix.bytesperline = formatInfo.bytesPerLine(width); + curV4L2Format_.fmt.pix.sizeimage = formatInfo.imageSize(width, 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; 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 +188,11 @@ 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); + PixelFormatInfo formatInfo = PixelFormatInfo::info(streamConfig.pixelFormat); + unsigned int width = streamConfig.size.width; + unsigned int height = streamConfig.size.height; + + return formatInfo.imageSize(width, height); } void V4L2CameraProxy::querycap(std::shared_ptr camera) @@ -253,12 +255,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; @@ -284,7 +287,8 @@ int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc * /* \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(streamConfig_.formats().pixelformats()[arg->index]).v4l2Format; memset(arg->reserved, 0, sizeof(arg->reserved)); @@ -306,7 +310,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 +322,14 @@ void V4L2CameraProxy::tryFormat(struct v4l2_format *arg) if (std::find(sizes.begin(), sizes.end(), size) == sizes.end()) size = streamConfig_.formats().sizes(format)[0]; + 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.width, size.height); 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 +354,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 +500,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 +841,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_;