[libcamera-devel] [PATCH v5] cam: kms_sink: Remove limitation that camera and display must match

Laurent Pinchart laurent.pinchart at ideasonboard.com
Mon Jun 20 13:59:47 CEST 2022


Hi Eric,

Thank you for the patch.

On Mon, Jun 20, 2022 at 12:52:39PM +0100, Eric Curtin wrote:
> There is a limitation that requires input and output to be pixel
> for pixel identical in terms of height and width. Remove this
> limitation to enable more hardware that doesn't match. Just start
> drawing from top left 0, 0 corner. Try and pick the mode closest to the
> stream size.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Eric Curtin <ecurtin at redhat.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Tested-by: Eric Curtin <ecurtin at redhat.com>
> ---
> Changes in v5:
> - Tested Laurents suggested change successfully
> - Added to commit message about trying to pick closest

I've also sent a v5, on Sunday (retaining your autorship of course). Did
I forget to CC you ?

> Changes in v4:
> - Change commit message to say top left
> - Spaces to tabs
> 
> Changes in v3:
> - Much simplified version of the patch where we just attempt to
>   draw from point 0, 0. Only in the case where we do not find a
>   matching mode. Can expand to do centralization, scaling, etc.
>   in further patches if needs be.
> 
> Changes in v2:
> - Tested and support drawing from negative pixel range
>   kernel parameter (video=960x540 at 60) was useful here
> ---
>  src/cam/kms_sink.cpp | 45 +++++++++++++++++++++++++++++++++++---------
>  1 file changed, 36 insertions(+), 9 deletions(-)
> 
> diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp
> index 7add81a6..7904bca8 100644
> --- a/src/cam/kms_sink.cpp
> +++ b/src/cam/kms_sink.cpp
> @@ -11,6 +11,7 @@
>  #include <algorithm>
>  #include <assert.h>
>  #include <iostream>
> +#include <limits.h>
>  #include <memory>
>  #include <stdint.h>
>  #include <string.h>
> @@ -112,6 +113,7 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
>  
>  	const libcamera::StreamConfiguration &cfg = config.at(0);
>  
> +	/* Find the best mode for the stream size. */
>  	const std::vector<DRM::Mode> &modes = connector_->modes();
>  	const auto iter = std::find_if(modes.begin(), modes.end(),
>  				       [&](const DRM::Mode &mode) {
> @@ -120,6 +122,32 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
>  				       });
>  	if (iter == modes.end()) {

I think you could drop this search, as the iteration over the modes
below should be enough. Would you mind testing the v5 I posted ?

>  		std::cerr << "No mode matching " << cfg.size << std::endl;
> +
> +		unsigned int cfgArea = cfg.size.width * cfg.size.height;
> +		unsigned int bestDistance = UINT_MAX;
> +
> +		for (const DRM::Mode &mode : modes) {
> +			unsigned int modeArea = mode.hdisplay * mode.vdisplay;
> +			unsigned int distance = modeArea > cfgArea
> +							? modeArea - cfgArea
> +							: cfgArea - modeArea;
> +
> +			if (distance < bestDistance) {
> +				mode_ = &mode;
> +				bestDistance = distance;
> +
> +				/*
> +				 * If the sizes match exactly, there will be no better
> +				 * match.
> +				 */
> +				if (distance == 0)
> +					break;
> +			}
> +		}
> +	}
> +
> +	if (!mode_) {
> +		std::cerr << "No modes\n";
>  		return -EINVAL;
>  	}
>  
> @@ -127,7 +155,6 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
>  	if (ret < 0)
>  		return ret;
>  
> -	mode_ = &*iter;
>  	size_ = cfg.size;
>  	stride_ = cfg.stride;
>  
> @@ -199,10 +226,10 @@ int KMSSink::configurePipeline(const libcamera::PixelFormat &format)
>  		return ret;
>  	}
>  
> -	std::cout
> -		<< "Using KMS plane " << plane_->id() << ", CRTC " << crtc_->id()
> -		<< ", connector " << connector_->name()
> -		<< " (" << connector_->id() << ")" << std::endl;
> +	std::cout << "Using KMS plane " << plane_->id() << ", CRTC "
> +		  << crtc_->id() << ", connector " << connector_->name() << " ("
> +		  << connector_->id() << "), mode " << mode_->hdisplay << "x"
> +		  << mode_->vdisplay << "@" << mode_->vrefresh << std::endl;
>  
>  	return 0;
>  }
> @@ -295,12 +322,12 @@ bool KMSSink::processRequest(libcamera::Request *camRequest)
>  		drmRequest->addProperty(plane_, "CRTC_ID", crtc_->id());
>  		drmRequest->addProperty(plane_, "SRC_X", 0 << 16);
>  		drmRequest->addProperty(plane_, "SRC_Y", 0 << 16);
> -		drmRequest->addProperty(plane_, "SRC_W", mode_->hdisplay << 16);
> -		drmRequest->addProperty(plane_, "SRC_H", mode_->vdisplay << 16);
> +		drmRequest->addProperty(plane_, "SRC_W", size_.width << 16);
> +		drmRequest->addProperty(plane_, "SRC_H", size_.height << 16);
>  		drmRequest->addProperty(plane_, "CRTC_X", 0);
>  		drmRequest->addProperty(plane_, "CRTC_Y", 0);
> -		drmRequest->addProperty(plane_, "CRTC_W", mode_->hdisplay);
> -		drmRequest->addProperty(plane_, "CRTC_H", mode_->vdisplay);
> +		drmRequest->addProperty(plane_, "CRTC_W", size_.width);
> +		drmRequest->addProperty(plane_, "CRTC_H", size_.height);
>  
>  		flags |= DRM::AtomicRequest::FlagAllowModeset;
>  	}

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list