summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-09-05 23:24:29 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-09-07 19:18:45 +0300
commit843048499fe1f1f8cea74838c1e3436945c1b1b7 (patch)
tree4d7f10086430d702bb2bdc23f9062b05cc2d8465
parentf8f6bc657d37e67c9f90762c8862a11e498925cc (diff)
cam: drm: Support per-plane stride values
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@ideasonboard.com> Reviewed-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r--src/cam/drm.cpp7
-rw-r--r--src/cam/drm.h5
-rw-r--r--src/cam/kms_sink.cpp28
3 files changed, 34 insertions, 6 deletions
diff --git a/src/cam/drm.cpp b/src/cam/drm.cpp
index da317e27..ac47b8bd 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 ee230402..00f7e798 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 8c0b79c6..658192ef 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 ? */
+ 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;