[libcamera-devel] [PATCH v3 23/30] cam: drm: Support per-plane stride values
Kieran Bingham
kieran.bingham at ideasonboard.com
Tue Sep 7 13:42:13 CEST 2021
On 06/09/2021 23:56, Laurent Pinchart wrote:
> The stride is not always identical for all planes for multi-planar
> formats. Semi-planar YUV formats without horizontal subsampling often
> have a chroma stride equal to twice the luma stride, and tri-planar YUV
> formats with a 1/2 horizontal subsampling often have a chroma stride
> equal to half the luma stride. This isn't correctly taken into account
> when creating a DRM frame buffer, as the same stride is set for all
> planes.
>
> libcamera doesn't report per-plane stride values yet, but uses chroma
> strides that match the above description for all currently supported
> platforms. Calculation the chrome strides appropriately in the KMSSink
> class, and pass them to DRM::createFrameBuffer().
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Reviewed-by: Jean-Michel Hautbois <jeanmichel.hautbois at ideasonboard.com>
> ---
> src/cam/drm.cpp | 7 +++----
> src/cam/drm.h | 5 ++++-
> src/cam/kms_sink.cpp | 28 +++++++++++++++++++++++++++-
> 3 files changed, 34 insertions(+), 6 deletions(-)
>
> diff --git a/src/cam/drm.cpp b/src/cam/drm.cpp
> index da317e27cb19..ac47b8bd3287 100644
> --- a/src/cam/drm.cpp
> +++ b/src/cam/drm.cpp
> @@ -595,12 +595,12 @@ const Object *Device::object(uint32_t id)
> std::unique_ptr<FrameBuffer> Device::createFrameBuffer(
> const libcamera::FrameBuffer &buffer,
> const libcamera::PixelFormat &format,
> - const libcamera::Size &size, unsigned int stride)
> + const libcamera::Size &size,
> + const std::array<uint32_t, 4> &strides)
> {
> std::unique_ptr<FrameBuffer> fb{ new FrameBuffer(this) };
>
> uint32_t handles[4] = {};
> - uint32_t pitches[4] = {};
> uint32_t offsets[4] = {};
> int ret;
>
> @@ -623,13 +623,12 @@ std::unique_ptr<FrameBuffer> Device::createFrameBuffer(
> fb->planes_.push_back({ handle });
>
> handles[i] = handle;
> - pitches[i] = stride;
> offsets[i] = 0; /* TODO */
> ++i;
> }
>
> ret = drmModeAddFB2(fd_, size.width, size.height, format.fourcc(), handles,
> - pitches, offsets, &fb->id_, 0);
> + strides.data(), offsets, &fb->id_, 0);
> if (ret < 0) {
> ret = -errno;
> std::cerr
> diff --git a/src/cam/drm.h b/src/cam/drm.h
> index ee2304025208..00f7e798b771 100644
> --- a/src/cam/drm.h
> +++ b/src/cam/drm.h
> @@ -7,9 +7,11 @@
> #ifndef __CAM_DRM_H__
> #define __CAM_DRM_H__
>
> +#include <array>
> #include <list>
> #include <map>
> #include <memory>
> +#include <stdint.h>
> #include <string>
> #include <vector>
>
> @@ -298,7 +300,8 @@ public:
> std::unique_ptr<FrameBuffer> createFrameBuffer(
> const libcamera::FrameBuffer &buffer,
> const libcamera::PixelFormat &format,
> - const libcamera::Size &size, unsigned int stride);
> + const libcamera::Size &size,
> + const std::array<uint32_t, 4> &strides);
>
> libcamera::Signal<AtomicRequest *> requestComplete;
>
> diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp
> index 8c0b79c63922..658192efc105 100644
> --- a/src/cam/kms_sink.cpp
> +++ b/src/cam/kms_sink.cpp
> @@ -7,10 +7,12 @@
>
> #include "kms_sink.h"
>
> +#include <array>
> #include <algorithm>
> #include <assert.h>
> #include <iostream>
> #include <memory>
> +#include <stdint.h>
> #include <string.h>
>
> #include <libcamera/camera.h>
> @@ -65,8 +67,32 @@ KMSSink::KMSSink(const std::string &connectorName)
>
> void KMSSink::mapBuffer(libcamera::FrameBuffer *buffer)
> {
> + std::array<uint32_t, 4> strides = {};
> +
> + /* \todo Should libcamera report per-plane strides ? */
Do you mean from the FrameBufferAllocator here?
Or to report the stride enforced from the V4L2 Device in some way?
But yes - if there are underlying stride requirements, they'll need to
be reported or discoverable right ?
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> + unsigned int uvStrideMultiplier;
> +
> + switch (format_) {
> + case libcamera::formats::NV24:
> + case libcamera::formats::NV42:
> + uvStrideMultiplier = 4;
> + break;
> + case libcamera::formats::YUV420:
> + case libcamera::formats::YVU420:
> + case libcamera::formats::YUV422:
> + uvStrideMultiplier = 1;
> + break;
> + default:
> + uvStrideMultiplier = 2;
> + break;
> + }
> +
> + strides[0] = stride_;
> + for (unsigned int i = 1; i < buffer->planes().size(); ++i)
> + strides[i] = stride_ * uvStrideMultiplier / 2;
> +
> std::unique_ptr<DRM::FrameBuffer> drmBuffer =
> - dev_.createFrameBuffer(*buffer, format_, size_, stride_);
> + dev_.createFrameBuffer(*buffer, format_, size_, strides);
> if (!drmBuffer)
> return;
>
>
More information about the libcamera-devel
mailing list