From 94cbaa381aa8b1b3f34ad8bf14989456ba79a9af Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 1 Sep 2021 23:22:40 +0300 Subject: libcamera: formats: Add planeSize() helpers to PixelFormatInfo 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 --- include/libcamera/internal/formats.h | 4 ++ src/android/mm/generic_camera_buffer.cpp | 13 ++---- src/android/yuv/post_processor_yuv.cpp | 10 ++--- src/libcamera/formats.cpp | 77 ++++++++++++++++++++++++++------ src/libcamera/v4l2_videodevice.cpp | 6 +-- 5 files changed, 75 insertions(+), 35 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index a07de6bc..b2869c93 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 27a30e2d..a4349f89 100644 --- a/src/android/mm/generic_camera_buffer.cpp +++ b/src/android/mm/generic_camera_buffer.cpp @@ -107,16 +107,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); - - planeInfo_[i].stride = stride; + const unsigned int planeSize = info.planeSize(size, i); + + 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 6952fc38..7b3b4960 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 1e5c8a0c..dd3e046e 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 84ccb974..1c4e6fbf 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; } } -- cgit v1.2.1