[libcamera-devel] [PATCH 2/3] pipeline: rkisp1: Fix validation when sensor max is larger than ISP input
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Wed Jan 17 17:21:00 CET 2024
Hi Paul
On Tue, Jan 16, 2024 at 06:17:53PM +0900, Paul Elder via libcamera-devel wrote:
> If the maximum sensor output size is larger than the maximum ISP input
> size, the maximum sensor size could be selected and the pipeline would
> fail with an EPIPE. Fix this by clamping the sensor size to the ISP
> input size at validation time.
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> ---
> src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 ++++++++++--
> src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 26 +++++++++----------
> src/libcamera/pipeline/rkisp1/rkisp1_path.h | 4 ++-
> 3 files changed, 30 insertions(+), 17 deletions(-)
>
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index 586b46d64..fb67ba8f4 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -1202,11 +1202,24 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
> if (param_->open() < 0)
> return false;
>
> + /*
> + * Retrieve ISP maximum input size for config validation in the path
> + * classes
> + */
> + Size ispMaxInSize = { 0, 0 };
> + V4L2Subdevice::Formats ispFormats = isp_->formats(0);
> + for (const auto &[mbus, sizes] : ispFormats) {
> + for (const auto &size : sizes) {
> + if (ispMaxInSize < size.max)
> + ispMaxInSize = size.max;
> + }
> + }
> +
I presume this could even be kept as a constant in the pipeline
handler ? Sure, retrieving it a run time is probably better
> /* Locate and open the ISP main and self paths. */
> - if (!mainPath_.init(media_))
> + if (!mainPath_.init(media_, ispMaxInSize))
> return false;
>
> - if (hasSelfPath_ && !selfPath_.init(media_))
> + if (hasSelfPath_ && !selfPath_.init(media_, ispMaxInSize))
> return false;
>
> mainPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady);
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> index b62b645ca..eaab7e857 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> @@ -62,7 +62,7 @@ RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats,
> {
> }
>
> -bool RkISP1Path::init(MediaDevice *media)
> +bool RkISP1Path::init(MediaDevice *media, const Size &ispMaxInSize)
> {
> std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
> std::string video = std::string("rkisp1_") + name_ + "path";
> @@ -76,6 +76,7 @@ bool RkISP1Path::init(MediaDevice *media)
> return false;
>
> populateFormats();
> + ispMaxInSize_ = ispMaxInSize;
>
> link_ = media->link("rkisp1_isp", 2, resizer, 0);
> if (!link_)
> @@ -172,7 +173,9 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
> /* Add all the RAW sizes the sensor can produce for this code. */
> for (const auto &rawSize : sensor->sizes(mbusCode)) {
> if (rawSize.width > maxResolution_.width ||
> - rawSize.height > maxResolution_.height)
> + rawSize.height > maxResolution_.height ||
> + rawSize.width > ispMaxInSize_.width ||
> + rawSize.height > ispMaxInSize_.height)
This filters out the streamFormats that are reported to the
application, and I think this should be maybe only limited by the
video capture device output sizes, not the isp input sizes ?
I do however see a few lines above in generateConfiguration()
const Size &resolution = sensor->resolution();
/* Min and max resolutions to populate the available stream formats. */
Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
.boundedTo(resolution);
Size minResolution = minResolution_.expandedToAspectRatio(resolution);
Should `resolution` be replaced by the maximum sensor resolution
smaller than the isp max input size (maybe computed in
populateFormats() ? )
> continue;
>
> streamFormats[format].push_back({ rawSize, rawSize });
> @@ -275,8 +278,9 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
> if (!found)
> cfg->pixelFormat = isRaw ? rawFormat : formats::NV12;
>
> - Size minResolution;
> - Size maxResolution;
> + Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
> + .boundedTo(resolution);
> + Size minResolution = minResolution_.expandedToAspectRatio(resolution);
Should you replace 'resolution' with the above mentioned 'larger
sensor's resolution which is smaller than the ISP input size' ?
>
> if (isRaw) {
> /*
> @@ -287,16 +291,10 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
> V4L2SubdeviceFormat sensorFormat =
> sensor->getFormat({ mbusCode }, cfg->size);
>
> - minResolution = sensorFormat.size;
> - maxResolution = sensorFormat.size;
> - } else {
> - /*
> - * Adjust the size based on the sensor resolution and absolute
> - * limits of the ISP.
> - */
> - minResolution = minResolution_.expandedToAspectRatio(resolution);
> - maxResolution = maxResolution_.boundedToAspectRatio(resolution)
> - .boundedTo(resolution);
> + if (!sensorFormat.size.isNull()) {
> + minResolution = sensorFormat.size.boundedTo(ispMaxInSize_);
> + maxResolution = sensorFormat.size.boundedTo(ispMaxInSize_);
> + }
> }
>
> cfg->size.boundTo(maxResolution);
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> index cd77957ee..c96bd5557 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
> @@ -35,7 +35,7 @@ public:
> RkISP1Path(const char *name, const Span<const PixelFormat> &formats,
> const Size &minResolution, const Size &maxResolution);
>
> - bool init(MediaDevice *media);
> + bool init(MediaDevice *media, const Size &ispMaxInSize);
I would creat the path with a pointer to the isp subdev instead of
passing the value here as this doesn't smell like a function parameter
but a system's characterstics . Not a big deal though.
>
> int setEnabled(bool enable) { return link_->setEnabled(enable); }
> bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
> @@ -77,6 +77,8 @@ private:
> std::unique_ptr<V4L2Subdevice> resizer_;
> std::unique_ptr<V4L2VideoDevice> video_;
> MediaLink *link_;
> +
> + Size ispMaxInSize_;
> };
>
> class RkISP1MainPath : public RkISP1Path
> --
> 2.39.2
>
More information about the libcamera-devel
mailing list