From patchwork Mon Sep 6 22:56:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13672 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 423A1BE175 for ; Mon, 6 Sep 2021 22:57:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EF02669180; Tue, 7 Sep 2021 00:57:06 +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="ttWRg0kd"; 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 F13EC6916A for ; Tue, 7 Sep 2021 00:57:00 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7A860891; Tue, 7 Sep 2021 00:57:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630969020; bh=gPr5UjzG2uC9IWNT501744MbdukW6WqdEIsA0DPdpWY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ttWRg0kdQwN7Be3HJ9v2pu0cphby7HE/SNqmml99Pe+92ISISeG67vjT+yaQNdQlz DbdM1kw4wE40qkzgmyhANzwxxoRw+EGsWI6VEz+g1r9oYqKEmtshJ7is0fOeP5R8q7 yw9qIH9DdPJG76lbocxDv0+AutlRCbTO/QtxdUIk= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 7 Sep 2021 01:56:12 +0300 Message-Id: <20210906225636.14683-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906225420.13275-1-laurent.pinchart@ideasonboard.com> References: <20210906225420.13275-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 06/30] libcamera: formats: Add planeSize() helpers to PixelFormatInfo 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 two helpers functions to the PixelFormatInfo class to compute the byte size of a given plane, taking the frame size, the stride, the alignment constraints and the vertical subsampling into account. Use the new functions through the code base to replace manual implementations. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Hirokazu Honda --- Changes since v1: - Factor out duplicated code --- include/libcamera/internal/formats.h | 4 ++ src/android/mm/generic_camera_buffer.cpp | 11 +--- src/android/yuv/post_processor_yuv.cpp | 10 ++- src/libcamera/formats.cpp | 77 +++++++++++++++++++----- src/libcamera/v4l2_videodevice.cpp | 6 +- 5 files changed, 74 insertions(+), 34 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index a07de6bc6020..b2869c93e960 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -41,6 +41,10 @@ public: unsigned int stride(unsigned int width, unsigned int plane, unsigned int align = 1) const; + unsigned int planeSize(const Size &size, unsigned int plane, + unsigned int align = 1) const; + unsigned int planeSize(unsigned int height, unsigned int plane, + unsigned int stride) const; unsigned int frameSize(const Size &size, unsigned int align = 1) const; unsigned int frameSize(const Size &size, const std::array &strides) const; diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp index 22efc4d4b13a..93aa5821e470 100644 --- a/src/android/mm/generic_camera_buffer.cpp +++ b/src/android/mm/generic_camera_buffer.cpp @@ -108,16 +108,9 @@ CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer, unsigned int offset = 0; for (unsigned int i = 0; i < numPlanes; ++i) { - /* - * \todo Remove if this plane size computation function is - * added to PixelFormatInfo. - */ - const unsigned int vertSubSample = info.planes[i].verticalSubSampling; - const unsigned int stride = info.stride(size.width, i, 1u); - const unsigned int planeSize = - stride * ((size.height + vertSubSample - 1) / vertSubSample); + const unsigned int planeSize = info.planeSize(size, i); - planeInfo_[i].stride = stride; + planeInfo_[i].stride = info.stride(size.width, i, 1u); planeInfo_[i].offset = offset; planeInfo_[i].size = planeSize; diff --git a/src/android/yuv/post_processor_yuv.cpp b/src/android/yuv/post_processor_yuv.cpp index 6952fc38b0ef..7b3b49609cb1 100644 --- a/src/android/yuv/post_processor_yuv.cpp +++ b/src/android/yuv/post_processor_yuv.cpp @@ -134,11 +134,9 @@ void PostProcessorYuv::calculateLengths(const StreamConfiguration &inCfg, sourceStride_[i] = inCfg.stride; destinationStride_[i] = nv12Info.stride(destinationSize_.width, i, 1); - const unsigned int vertSubSample = - nv12Info.planes[i].verticalSubSampling; - sourceLength_[i] = sourceStride_[i] * - ((sourceSize_.height + vertSubSample - 1) / vertSubSample); - destinationLength_[i] = destinationStride_[i] * - ((destinationSize_.height + vertSubSample - 1) / vertSubSample); + sourceLength_[i] = nv12Info.planeSize(sourceSize_.height, i, + sourceStride_[i]); + destinationLength_[i] = nv12Info.planeSize(destinationSize_.height, i, + destinationStride_[i]); } } diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index c993960eb982..ce0081a8a3d1 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -11,6 +11,7 @@ #include #include +#include #include @@ -801,32 +802,80 @@ unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane, } /** - * \brief Compute the number of bytes necessary to store a frame + * \brief Compute the number of bytes necessary to store a plane of a frame * \param[in] size The size of the frame, in pixels + * \param[in] plane The plane index * \param[in] align The stride alignment, in bytes (1 for default alignment) * - * The frame is computed by adding the product of the line stride and the frame - * height for all planes, taking subsampling and other format characteristics - * into account. Additional stride alignment constraints may be specified - * through the \a align parameter, and will apply to all planes. For more - * complex stride constraints, use the frameSize() overloaded version that takes - * an array of stride values. + * The plane size is computed by multiplying the line stride and the frame + * height, taking subsampling and other format characteristics into account. + * Stride alignment constraints may be specified through the \a align parameter. * * \sa stride() * + * \return The number of bytes necessary to store the plane, or 0 if the + * PixelFormatInfo instance is not valid or the plane number isn't valid for the + * format + */ +unsigned int PixelFormatInfo::planeSize(const Size &size, unsigned int plane, + unsigned int align) const +{ + unsigned int stride = PixelFormatInfo::stride(size.width, plane, align); + if (!stride) + return 0; + + return planeSize(size.height, plane, stride); +} + +/** + * \brief Compute the number of bytes necessary to store a plane of a frame + * \param[in] height The height of the frame, in pixels + * \param[in] plane The plane index + * \param[in] stride The plane stride, in bytes + * + * The plane size is computed by multiplying the line stride and the frame + * height, taking subsampling and other format characteristics into account. + * Stride alignment constraints may be specified through the \a align parameter. + * + * \return The number of bytes necessary to store the plane, or 0 if the + * PixelFormatInfo instance is not valid or the plane number isn't valid for the + * format + */ +unsigned int PixelFormatInfo::planeSize(unsigned int height, unsigned int plane, + unsigned int stride) const +{ + unsigned int vertSubSample = planes[plane].verticalSubSampling; + if (!vertSubSample) + return 0; + + /* stride * ceil(height / verticalSubSampling) */ + return stride * ((height + vertSubSample - 1) / vertSubSample); +} + +/** + * \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 stride alignment, in bytes (1 for default alignment) + * + * The frame size is computed by adding the size of all planes, as computed by + * planeSize(), using the specified alignment constraints for all planes. For + * more complex stride constraints, use the frameSize() overloaded version that + * takes an array of stride values. + * + * \sa planeSize() + * * \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); + + for (const auto &[i, plane] : utils::enumerate(planes)) { + if (plane.bytesPerGroup == 0) + break; + + sum += planeSize(size, i, align); } return sum; diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 84ccb97495f5..1c4e6fbf7fe7 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1337,11 +1337,7 @@ std::unique_ptr V4L2VideoDevice::createBuffer(unsigned int index) planes[i].offset = offset; /* \todo Take the V4L2 stride into account */ - const unsigned int vertSubSample = - info.planes[i].verticalSubSampling; - planes[i].length = - info.stride(format_.size.width, i, 1u) * - ((format_.size.height + vertSubSample - 1) / vertSubSample); + planes[i].length = info.planeSize(format_.size, i); offset += planes[i].length; } }