[libcamera-devel] [PATCH] cam: kms_sink: Add color space support
Eric Curtin
ecurtin at redhat.com
Wed Sep 28 12:00:45 CEST 2022
On Wed, 28 Sept 2022 at 02:49, Laurent Pinchart via libcamera-devel
<libcamera-devel at lists.libcamera.org> wrote:
>
> KMS defines YCbCr encoding and quantization properties for planes. When
> supported by the device, set them to match the color space of the
> stream to render colors accurately.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> src/cam/kms_sink.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++
> src/cam/kms_sink.h | 3 ++
> 2 files changed, 83 insertions(+)
>
> diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp
> index 17e2fa69bff7..754b061eebf7 100644
> --- a/src/cam/kms_sink.cpp
> +++ b/src/cam/kms_sink.cpp
> @@ -149,6 +149,81 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
> size_ = cfg.size;
> stride_ = cfg.stride;
>
> + /* Configure color space. */
> + colorEncoding_ = std::nullopt;
> + colorRange_ = std::nullopt;
> +
> + if (cfg.colorSpace->ycbcrEncoding == libcamera::ColorSpace::YcbcrEncoding::None)
> + return 0;
> +
> + /*
> + * The encoding and range enums are defined in the kernel but not
> + * exposed in public headers.
> + */
> + enum drm_color_encoding {
> + DRM_COLOR_YCBCR_BT601,
> + DRM_COLOR_YCBCR_BT709,
> + DRM_COLOR_YCBCR_BT2020,
> + };
> +
> + enum drm_color_range {
> + DRM_COLOR_YCBCR_LIMITED_RANGE,
> + DRM_COLOR_YCBCR_FULL_RANGE,
> + };
> +
> + const DRM::Property *colorEncoding = plane_->property("COLOR_ENCODING");
> + const DRM::Property *colorRange = plane_->property("COLOR_RANGE");
> +
> + if (colorEncoding) {
> + drm_color_encoding encoding;
> +
> + switch (cfg.colorSpace->ycbcrEncoding) {
> + case libcamera::ColorSpace::YcbcrEncoding::Rec601:
> + default:
> + encoding = DRM_COLOR_YCBCR_BT601;
> + break;
> + case libcamera::ColorSpace::YcbcrEncoding::Rec709:
> + encoding = DRM_COLOR_YCBCR_BT709;
> + break;
> + case libcamera::ColorSpace::YcbcrEncoding::Rec2020:
> + encoding = DRM_COLOR_YCBCR_BT2020;
> + break;
> + }
> +
> + for (const auto &[id, name] : colorEncoding->enums()) {
> + if (id == encoding) {
> + colorEncoding_ = encoding;
> + break;
> + }
> + }
> + }
> +
> + if (colorRange) {
> + drm_color_range range;
> +
> + switch (cfg.colorSpace->range) {
> + case libcamera::ColorSpace::Range::Limited:
> + default:
> + range = DRM_COLOR_YCBCR_LIMITED_RANGE;
> + break;
> + case libcamera::ColorSpace::Range::Full:
> + range = DRM_COLOR_YCBCR_FULL_RANGE;
> + break;
> + }
> +
> + for (const auto &[id, name] : colorRange->enums()) {
> + if (id == range) {
> + colorRange_ = range;
> + break;
> + }
> + }
> + }
> +
> + if (!colorEncoding_ || !colorRange_)
> + std::cerr << "Color space " << cfg.colorSpace->toString()
> + << " not supported by the display device."
> + << " Colors may be wrong." << std::endl;
> +
> return 0;
> }
>
> @@ -415,6 +490,11 @@ bool KMSSink::processRequest(libcamera::Request *camRequest)
> drmRequest->addProperty(plane_, "CRTC_W", dst_.width);
> drmRequest->addProperty(plane_, "CRTC_H", dst_.height);
>
> + if (colorEncoding_)
> + drmRequest->addProperty(plane_, "COLOR_ENCODING", *colorEncoding_);
> + if (colorRange_)
> + drmRequest->addProperty(plane_, "COLOR_RANGE", *colorRange_);
> +
> flags |= DRM::AtomicRequest::FlagAllowModeset;
> }
>
> diff --git a/src/cam/kms_sink.h b/src/cam/kms_sink.h
> index 76c4e611bf85..e2c618a19035 100644
> --- a/src/cam/kms_sink.h
> +++ b/src/cam/kms_sink.h
> @@ -10,6 +10,7 @@
> #include <list>
> #include <memory>
> #include <mutex>
> +#include <optional>
> #include <string>
> #include <utility>
>
> @@ -67,6 +68,8 @@ private:
> libcamera::PixelFormat format_;
> libcamera::Size size_;
> unsigned int stride_;
> + std::optional<unsigned int> colorEncoding_;
> + std::optional<unsigned int> colorRange_;
>
> libcamera::Rectangle src_;
> libcamera::Rectangle dst_;
> --
> Regards,
>
> Laurent Pinchart
>
LGTM
Reviewed-by: Eric Curtin <ecurtin at redhat.com>
More information about the libcamera-devel
mailing list