[PATCH] pipeline: rkisp1: Fix validation when sensor max is larger than ISP input
Umang Jain
umang.jain at ideasonboard.com
Wed Jul 24 12:28:12 CEST 2024
From: Paul Elder <paul.elder at ideasonboard.com>
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 validating a suitable sensor output size
which is less than or equal to, the ISP input.
Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
---
Split out from https://patchwork.libcamera.org/project/libcamera/list/?series=4143
Changes in v2:
- trivial var rename
- Properly obtain a resolution from sensor supported for ISP max input
- Refactor slightly to fit better
---
src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 ++++++-
src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 51 +++++++++++++------
src/libcamera/pipeline/rkisp1/rkisp1_path.h | 5 +-
3 files changed, 55 insertions(+), 18 deletions(-)
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 4cbf105d..5f94f422 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 the ISP maximum input size for config validation in the
+ * path classes.
+ */
+ Size ispMaxInputSize;
+ V4L2Subdevice::Formats ispFormats = isp_->formats(0);
+ for (const auto &[mbus, sizes] : ispFormats) {
+ for (const auto &size : sizes) {
+ if (ispMaxInputSize < size.max)
+ ispMaxInputSize = size.max;
+ }
+ }
+
/* Locate and open the ISP main and self paths. */
- if (!mainPath_.init(media_))
+ if (!mainPath_.init(media_, ispMaxInputSize))
return false;
- if (hasSelfPath_ && !selfPath_.init(media_))
+ if (hasSelfPath_ && !selfPath_.init(media_, ispMaxInputSize))
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 c49017d1..6b40cdd2 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 &ispMaxInputSize)
{
std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
std::string video = std::string("rkisp1_") + name_ + "path";
@@ -75,6 +75,7 @@ bool RkISP1Path::init(MediaDevice *media)
if (video_->open() < 0)
return false;
+ ispMaxInputSize_ = ispMaxInputSize;
populateFormats();
link_ = media->link("rkisp1_isp", 2, resizer, 0);
@@ -126,12 +127,33 @@ void RkISP1Path::populateFormats()
}
}
+Size RkISP1Path::maxSupportedSensorResolution(const CameraSensor *sensor)
+{
+ Size sensorResolution;
+
+ /* Get highest sensor resolution which is just less than or equal to ISP input */
+ for (const auto &format : streamFormats_) {
+ auto sizes = sensor->sizes(formatToMediaBus.at(format));
+ for (auto &sz : sizes) {
+ if (sz <= ispMaxInputSize_ && sz > sensorResolution)
+ sensorResolution = sz;
+ }
+ }
+
+ return sensorResolution;
+}
+
StreamConfiguration
RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
StreamRole role)
{
const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
- const Size &resolution = sensor->resolution();
+ Size resolution = maxSupportedSensorResolution(sensor);
+ if (resolution.isNull()) {
+ LOG(RkISP1, Error) << "No suitable format/resolution found"
+ << "for ISP input";
+ return {};
+ }
/* Min and max resolutions to populate the available stream formats. */
Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
@@ -220,7 +242,12 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
StreamConfiguration *cfg)
{
const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
- const Size &resolution = sensor->resolution();
+ Size resolution = maxSupportedSensorResolution(sensor);
+ if (resolution.isNull()) {
+ LOG(RkISP1, Error) << "No suitable format/resolution found"
+ << "for ISP input";
+ return {};
+ }
const StreamConfiguration reqCfg = *cfg;
CameraConfiguration::Status status = CameraConfiguration::Valid;
@@ -275,8 +302,8 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
if (!found)
cfg->pixelFormat = isRaw ? rawFormat : formats::NV12;
- Size minResolution;
- Size maxResolution;
+ Size maxResolution = maxResolution_.boundedTo(resolution);
+ Size minResolution = minResolution_.expandedToAspectRatio(resolution);
if (isRaw) {
/*
@@ -287,16 +314,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(ispMaxInputSize_);
+ maxResolution = sensorFormat.size.boundedTo(ispMaxInputSize_);
+ }
}
cfg->size.boundTo(maxResolution);
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index 08edefec..a9bcfe36 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 &ispMaxInputSize);
int setEnabled(bool enable) { return link_->setEnabled(enable); }
bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
@@ -63,6 +63,7 @@ public:
private:
void populateFormats();
+ Size maxSupportedSensorResolution(const CameraSensor *sensor);
static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
@@ -77,6 +78,8 @@ private:
std::unique_ptr<V4L2Subdevice> resizer_;
std::unique_ptr<V4L2VideoDevice> video_;
MediaLink *link_;
+
+ Size ispMaxInputSize_;
};
class RkISP1MainPath : public RkISP1Path
--
2.45.2
More information about the libcamera-devel
mailing list